using System.Collections.Concurrent; using Microsoft.AspNetCore.SignalR; namespace PongGame.Hubs; public class PongLobby { private readonly HashSet connectedPlayers = new(); private readonly Dictionary PongRooms = new(); public PongLobby(ILogger logger) => Logger = logger; public const int ROOM_ID_LENGTH = 4; public PongPlayer CreatePlayer() { var player = new PongPlayer(); lock (connectedPlayers) connectedPlayers.Add(player); return player; } public void RemovePlayer(PongPlayer player) { if (player.ConnectedRoom is PongRoom room) room.Leave(player); lock (connectedPlayers) _ = connectedPlayers.Remove(player); } public PongRoom CreateRoom(PongPlayer player) { PongRoom room; lock (PongRooms) { room = new(GenerateRoomId(), Logger); PongRooms.Add(room.ID, room); } room.Join(player); return room; } public PongRoom JoinRoom(PongPlayer player, string roomId) { PongRoom? room; lock (PongRooms) { room = PongRooms.GetValueOrDefault(roomId); } if (room is null) throw new HubException($"Room [{roomId}] not found!"); room.Join(player); return room; } public void LeaveRoom(PongPlayer player) { if (player.ConnectedRoom is PongRoom room) room.Leave(player); } private readonly Random random = new(); private readonly ILogger Logger; private const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private string GenerateRoomId() { string id; do { id = string.Concat(Enumerable.Range(0, ROOM_ID_LENGTH).Select(_ => ALPHABET[random.Next(ALPHABET.Length)])); } while (PongRooms.ContainsKey(id)); return id; } }