SpotifyRoulette/src/main/java/eric/Roullette/service/GameService.java

114 lines
5.1 KiB
Java

package eric.Roullette.service;
import eric.Roullette.dto.PlayersMessage;
import eric.Roullette.util.JsonUtil;
import io.javalin.websocket.WsContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.*;
public class GameService {
private static final Logger log = LoggerFactory.getLogger(GameService.class);
private final SpotifyAuthService authService;
private final Map<String, Set<WsContext>> sessions = new ConcurrentHashMap<>();
private final Map<String, Game> games = new ConcurrentHashMap<>();
public GameService(SpotifyAuthService authService) { // <-- Konstruktor
this.authService = authService;
}
public Map<String, List<String>> getTrackInfos(Map<String, List<String>> allPlayerTracks) {
// für jeden String Spieler in allPlayerTracks die Liste der Tracks an authservice übergeben
Map<String, List<String>> trackInfos = new ConcurrentHashMap<>();
for (Map.Entry<String, List<String>> entry : allPlayerTracks.entrySet()) {
String player = entry.getKey();
List<String> tracks = entry.getValue();
if (tracks.isEmpty()) continue; // Keine Tracks, skip
try {
List<String> trackInfo = authService.getTrackInfos(tracks);
trackInfos.put(player, trackInfo);
} catch (Exception e) {
log.error("Fehler beim Abrufen der Track-Infos für Spieler {}: {}", player, e.getMessage());
}
}
return trackInfos;
}
public record Game(String id, List<String> players, Map<String,Integer> scores, String currentOwner,
String currentSong, List<String> allTracks, Map<String, List<String>> playerTracks) {
public static Game create(String id) {
return new Game(id, new CopyOnWriteArrayList<>(), new ConcurrentHashMap<>(), null, null, new ArrayList<>(), new ConcurrentHashMap<>());
}
}
public Game getOrCreateGame(String gameId) {
return games.computeIfAbsent(gameId, Game::create);
}
public void addPlayer(String gameId, String user) throws InterruptedException {
Game g = getOrCreateGame(gameId);
if (user != null && !g.players().contains(user)) {
g.players().add(user);
g.scores().putIfAbsent(user, 0);
// Songs einmalig laden und speichern
List<String> tracks = authService.getRecentTracks(user);
g.playerTracks().put(user, tracks);
}
}
public void registerSession(String gameId, WsContext ctx) {
sessions
.computeIfAbsent(gameId, id -> ConcurrentHashMap.newKeySet())
.add(ctx);
broadcastPlayers(gameId);
}
public void removeSession(String gameId, WsContext ctx) {
sessions.getOrDefault(gameId, Collections.emptySet()).remove(ctx);
broadcastPlayers(gameId);
}
public void broadcastPlayers(String gameId) {
Game game = games.get(gameId);
if (game == null) return;
PlayersMessage msg = new PlayersMessage(new ArrayList<>(game.players()));
sessions.getOrDefault(gameId, Collections.emptySet())
.forEach(ctx -> ctx.send(JsonUtil.toJson(msg)));
}
public void createGame(String gameId) {
Game game = new Game(gameId, new CopyOnWriteArrayList<>(), new ConcurrentHashMap<>(), null, null, new ArrayList<>(), new ConcurrentHashMap<>());
games.put(gameId, game);
}
public boolean gameExists(String gameId) {
return games.containsKey(gameId);
}
public Game startRound(String gameId, List<String> uris) {
Game g = getOrCreateGame(gameId);
if (g.players().isEmpty()) throw new IllegalStateException("No players");
String owner = g.players().get(ThreadLocalRandom.current().nextInt(g.players().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;
}
public Set<WsContext> getSessions(String gameId) {
return sessions.getOrDefault(gameId, Collections.emptySet());
}
// Map<Player, List<Track>>
public Map<String, List<String>> getPlayerTracks(String gameId) {
Game game = games.get(gameId);
if (game == null) return Collections.emptyMap();
return game.playerTracks();
}
}