using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MafiaTelegramBot.Game; using MafiaTelegramBot.Game.GameRooms; using MafiaTelegramBot.Resources; namespace MafiaTelegramBot.Controllers { public static class RoomController { private static readonly Dictionary OpenedGames = new(); public static async Task CreateNewGame(Player creator, string roomName, bool isExtended, bool isPrivate, bool isRanking) { return await Task.Run(() => { var roomKey = RoomEncrypter.GetCode(roomName); if (OpenedGames.ContainsKey(roomKey)) return ResultCode.GameAlreadyExists; if (!creator.SetRoomName(roomName)) return ResultCode.UserAlreadyInGame; GameRoom room = isExtended ? new ExtendedGameRoom {Owner = creator, RoomName = roomName, IsPrivate = isPrivate, IsRanking = isRanking} : new NormalGameRoom {Owner = creator, RoomName = roomName, IsPrivate = isPrivate, IsRanking = isRanking}; OpenedGames.Add(roomKey, room); room.Players.Add(creator.Id, creator); room.SetTimer(); return ResultCode.CodeOk; }); } public static async Task ConnectToGame(Player player, string roomKey) { return await Task.Run(async () => { if (!OpenedGames.ContainsKey(roomKey)) return ResultCode.RoomDoesNotExist; var roomName = RoomEncrypter.GetName(roomKey); if (OpenedGames[roomKey].IsRunning) return ResultCode.GameAlreadyRunning; if (OpenedGames[roomKey].IsFilled()) return ResultCode.RoomIsFilled; if (!player.SetRoomName(roomName)) return ResultCode.UserAlreadyInGame; OpenedGames[roomKey].Players.Add(player.Id, player); if (OpenedGames[roomKey].Players.Count > Constants.MEMORY_CLEANER_PLAYERS_COUNT) OpenedGames[roomKey].StopTimer(); await OpenedGames[roomKey].PlayersMessageChannel.SendExcept(player.Id, $"{player.NickName} {strings.connected_to_game}"); OpenedGames[roomKey].PlayersMessageChannel.AddPerson(player.ChatId); return ResultCode.CodeOk; }); } public static List GetPlayers(string roomKey) { return OpenedGames[roomKey].Players.Values.ToList(); } public static async Task LeaveFromGame(Player player) { return await Task.Run(async () => { var roomName = player.GetRoomName(); var roomKey = RoomEncrypter.GetCode(roomName); if (!player.RemoveGame()) return ResultCode.UserNotInGame; await OpenedGames[roomKey].Leave(player); if (!OpenedGames[roomKey].IsRunning && OpenedGames[roomKey].Players.Count <= Constants.MEMORY_CLEANER_INTERVAL) OpenedGames[roomKey].StartTimer(); if (OpenedGames[roomKey].Players.Count >= 0) return ResultCode.CodeOk; RoomEncrypter.RemoveCode(roomName); OpenedGames.Remove(roomKey); return ResultCode.CodeOk; }); } public static async Task DissolveRoom(string roomKey) { await Task.Run(async () => { if (OpenedGames.ContainsKey(roomKey)) { foreach (var player in OpenedGames[roomKey].Players.Values) { await OpenedGames[roomKey].PlayersMessageChannel.SendTo(player.Id, strings.room_dissolved, player.IsAdmin ? Keyboard.AdminMainMenu : Keyboard.MainMenu); player.RemoveGame(); player.ResetState(); } RoomEncrypter.RemoveCode(OpenedGames[roomKey].RoomName); OpenedGames[roomKey].DeleteTimer(); OpenedGames.Remove(roomKey); } }); } public static async Task> GetPublicNotRankedRooms() { return await Task.Run(() => { async Task Comparison(GameRoom room, GameRoom room2) { var first = await room.GetCapacity() / (double) await room.GetMaximum(); var second = await room2.GetCapacity() / (double) await room2.GetMaximum(); return second > first ? 1 : 0; } var rooms = OpenedGames.Values .Where(room => !room.IsPrivate && !room.IsFilled() && !room.IsRunning && !room.IsRanking). ToList(); rooms.Sort((room, room2) => Comparison(room, room2).Result); return rooms; }); } public static async Task> GetPublicRankedRooms(char rank) { return await Task.Run(() => { async Task Comparison(GameRoom room, GameRoom room2) { var first = await room.GetCapacity() / (double) await room.GetMaximum(); var second = await room2.GetCapacity() / (double) await room2.GetMaximum(); return second > first ? 1 : 0; } bool IsNeighborRank(char roomRank, char playerRank) { return roomRank - playerRank > -2 && roomRank - playerRank < 2; } var rooms = OpenedGames.Values .Where(room => !room.IsPrivate && !room.IsFilled() && !room.IsRunning && room.IsRanking && IsNeighborRank(room.GetRoomRank().Result, rank)). ToList(); rooms.Sort((room, room2) => Comparison(room, room2).Result); return rooms; }); } public static GameRoom GetRoom(string roomKey) { return OpenedGames[roomKey]; } } }