Merge pull request 'Optimierungen' (#48) from Optimierungen into main

Reviewed-on: #48
pull/49/head
Eric Paci 2025-08-12 03:09:10 +02:00
commit 86cecfee9e
7 changed files with 109 additions and 57 deletions

View File

@ -62,13 +62,11 @@ public class GameController {
userAccessTokens.put(username, playerAccessToken);
}
}
if (accessToken == null) {
ctx.status(401).result("Zugriffstoken fehlt oder ist ungültig");
if (!userAccessTokens.containsKey(username)) {
ctx.status(401).result("Zugriffstoken für Benutzer " + username + " nicht gefunden.");
return;
}
var devices = authService.getDevices(accessToken);
var devices = authService.getDevices(userAccessTokens.get(username));
ctx.json(devices);
});

View File

@ -92,7 +92,11 @@ package eric.Roullette.service;
Game g = getOrCreateGame(gameId);
if (g.players().isEmpty()) throw new IllegalStateException("No players");
String owner = g.players().get(ThreadLocalRandom.current().nextInt(g.players().size()));
String song = uris.get(ThreadLocalRandom.current().nextInt(uris.size()));
List<String> ownerTracks = g.playerTracks().getOrDefault(owner, List.of());
if (ownerTracks.isEmpty()) throw new IllegalStateException("Owner hat keine Tracks");
String song = ownerTracks.get(ThreadLocalRandom.current().nextInt(ownerTracks.size()));
//String song = uris.get(ThreadLocalRandom.current().nextInt(uris.size()));
Game updated = new Game(gameId, g.players(), g.scores(), owner, song, uris, g.playerTracks());
games.put(gameId, updated);
return updated;

View File

@ -51,7 +51,7 @@ public class SpotifyAuthService {
return tempApi.authorizationCodeUri()
.scope(scope)
.state(user) // Der Benutzername wird im State mitgegeben
.show_dialog(true)
//.show_dialog(true)
.build()
.execute();
}
@ -85,47 +85,47 @@ public class SpotifyAuthService {
SpotifyApi userApi = userApis.get(user);
if (userApi == null) {
System.out.println("Kein SpotifyApi-Client für Benutzer gefunden: " + user);
System.err.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());
// 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);
//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());
//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("Erstelle Anfrage für kürzlich gespielte Tracks...");
// if (userApi.getRefreshToken() == null) {
// System.err.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("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.");
// 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...");
// System.out.println("Führe paging Anfrage aus...");
PagingCursorbased<PlayHistory> history = request.execute();
System.out.println("Paging Anfrage erfolgreich ausgeführt.");
// System.out.println("Paging Anfrage erfolgreich ausgeführt.");
// Überprüfe, ob die Ergebnisse leer sind
System.out.println("Überprüfe, ob Ergebnisse vorhanden 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...");
// System.out.println("Verarbeite kürzlich gespielte Tracks...");
// Extrahiere die URIs der kürzlich gespielten Tracks
List<String> recentTracks = Arrays.stream(history.getItems())
.map(item -> item.getTrack().getUri())
@ -134,6 +134,7 @@ public class SpotifyAuthService {
System.out.println("Gefundene kürzlich gespielte Tracks: " + recentTracks.size());
if (recentTracks.size() < limit) {
int oldLimit = limit;
int newLimit = limit - recentTracks.size();
// restliche songs mit kürzlich gespeicherten Tracks auffüllen
List<String> savedTracks = getSavedTracks(user, newLimit, 0);
@ -142,8 +143,9 @@ public class SpotifyAuthService {
recentTracks = new java.util.ArrayList<>(recentTracks);
recentTracks.addAll(savedTracks.subList(0, Math.min(newLimit, savedTracks.size())));
if(recentTracks.size() < limit){
oldLimit = newLimit;
newLimit = limit - recentTracks.size();
List<String> savedTracks2 = getSavedTracks(user, newLimit, 50);
List<String> savedTracks2 = getSavedTracks(user, newLimit, oldLimit);
savedTracks2.removeAll(recentTracks);
recentTracks.addAll(savedTracks2.subList(0, Math.min(newLimit, savedTracks2.size())));
}

View File

@ -52,7 +52,19 @@ public class GameWebSocketHandler {
// Connection geschlossen
ws.onClose(ctx -> {
String gameId = ctx.pathParam("gameId");
String username = ctx.queryParam("username");
service.removeSession(gameId, ctx);
// Spieler aus der Spielerliste entfernen
var game = service.getOrCreateGame(gameId);
if (username != null && game.players().contains(username)) {
game.players().remove(username);
game.scores().remove(username);
// Optional: auch die Tracks entfernen
game.playerTracks().remove(username);
}
service.broadcastPlayers(gameId);
});
// Eingehende Nachrichten (Guesses & Player-Requests)
@ -88,14 +100,36 @@ public class GameWebSocketHandler {
.flatMap(List::stream)
.toList();
System.out.println("AlltracksCache für Spiel " + gameId + " hat " + allTracks.size() + " Songs (rundenstart)");
//Trackinfos für alle Spieler sammeln
if(playerTrackInfoCache.containsKey(gameId)){
// Wenn der Cache schon existiert, dann nur die Trackinfos nutzen
System.out.println("TrackInfosCache für Spiel " + gameId + " existiert bereits (rundenstart)");
// prüfen ob ein neuer spieler dazugekommen ist
if( allPlayerTracks.size() > playerTrackInfoCache.get(gameId).size()) {
System.out.println("Neuer Spieler hinzugefügt, Trackinfos werden aktualisiert (rundenstart)");
Map<String, List<String>> allTrackInfos = service.getTrackInfos(allPlayerTracks);
// Cache für Trackinfos pro Spiel-ID aktualisieren
playerTrackInfoCache.put(gameId, allTrackInfos);
} else {
System.out.println("Keine neuen Spieler, Trackinfos bleiben unverändert (rundenstart)");
}
} else {
// Wenn der Cache nicht existiert, dann Trackinfos sammeln
System.out.println("TrackInfosCache für Spiel " + gameId + " wird erstellt (rundenstart)");
Map<String, List<String>> allTrackInfos = service.getTrackInfos(allPlayerTracks);
// Cache für Trackinfos pro Spiel-ID
playerTrackInfoCache.put(gameId, allTrackInfos);
}
System.out.println("TrackInfosCache für Spiel " + gameId + " hat " + playerTrackInfoCache.get(gameId).size() + " Spieler (rundenstart)");
if (!allTracks.isEmpty()) {
service.startRound(gameId, allTracks);
}
// Trackinfos für alle Spieler sammeln
//Map<String, List<String>> 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)");
//
broadcastRoundStart(gameId);
}
}
@ -149,12 +183,19 @@ private void broadcastRoundResult(String gameId) {
Map<String,String> guesses = currentGuesses.remove(gameId);
String owner = game.currentOwner();
// System.out.println("Owner: " + owner);
// System.out.println("Guesses: " + guesses);
// System.out.println("Scores vor Auswertung: " + scores);
// Für jeden Tippenden Score anpassen
for (Map.Entry<String, String> entry : guesses.entrySet()) {
String guesser = entry.getKey();
boolean correct = owner.equals(entry.getValue());
scores.merge(guesser, correct ? 3 : -1, Integer::sum);
}
// System.out.println("Owner: " + owner);
// System.out.println("Guesses: " + guesses);
// System.out.println("Scores nach Auswertung: " + scores);
String msg = JsonUtil.toJson(Map.of(
"type", "round-result",
@ -165,22 +206,24 @@ private void broadcastRoundResult(String gameId) {
broadcastToAll(gameId, msg);
// Prüfe auf Gewinner
String winner = scores.entrySet().stream()
.filter(e -> e.getValue() >= 6)
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
if (winner != null) {
// Broadcast an alle, dass das Spiel vorbei ist
String winMsg = JsonUtil.toJson(Map.of(
"type", "game-end",
"winner", winner,
"scores", scores
));
broadcastToAll(gameId, winMsg);
game.scores().replaceAll((user , pts) -> 0); // Reset Scores für alle Spieler
// Nur beenden, wenn EIN Spieler allein die höchste Punktzahl >= score hat
int score = 6;
int max = scores.values().stream().max(Integer::compareTo).orElse(0);
List<String> topScorers = scores.entrySet().stream()
.filter(e -> e.getValue() == max && max >= score)
.map(Map.Entry::getKey)
.toList();
}
if (topScorers.size() == 1) {
String winner = topScorers.get(0);
String winMsg = JsonUtil.toJson(Map.of(
"type", "game-end",
"winner", winner,
"scores", scores
));
broadcastToAll(gameId, winMsg);
game.scores().replaceAll((user , pts) -> 0); // Reset Scores
}
// else{
// // nächste Runde starten
// // ...

View File

@ -1,6 +1 @@
spring.application.name=Roullette
spotify:
client-id: 70c36cd6e2d54ad0ba2e60ef6334bbc8
client-secret: 116188574dd140eab1973e75c7e5ecfe
redirect-uri: https://www.davidmagkuchen.de/spotify/callback

View File

@ -18,6 +18,13 @@ area.appendChild(select);
async function loadDevices() {
select.innerHTML = "";
// Standardoption "Kein Gerät"
const noneOpt = document.createElement("option");
noneOpt.value = "";
noneOpt.textContent = "Kein Gerät";
select.appendChild(noneOpt);
const devices = await fetchJson(`/api/spotify/devices?username=${encodeURIComponent(username)}`);
if (!devices.length) {
const opt = document.createElement("option");
@ -34,6 +41,8 @@ async function loadDevices() {
select.appendChild(opt);
});
select.disabled = false;
select.value = ""; // "Kein Gerät" als Standard
}
loadDevices();

View File

@ -316,8 +316,9 @@ function handleGameEnd({ winner }) {
// Spotify-Playback Funktion (unverändert)
async function playOnSpotify(trackUri, username) {
const deviceId = document.getElementById("deviceSelect")?.value;
if (!deviceId) {
alert("Bitte ein Wiedergabegerät auswählen!");
if (deviceId === "") {
//alert("Bitte ein Wiedergabegerät auswählen!");
//keine warnung i guess
return;
}
try {