import Foundation import WebSocketKit let maximumPlayersPerTable = 4 typealias TableId = String typealias TableName = String final class TableManagement { /// A list of table ids for public games private var publicTables = Set() /// A mapping from table id to table name (for all tables) private var tableNames = [TableId: TableName]() /// A mapping from table id to participating players private var tablePlayers = [TableId: [PlayerName]]() /// A reverse list of players and their table id private var playerTables = [PlayerName: TableId]() private var playerConnections = [PlayerName : WebSocket]() init() { } /** Create a new table with optional players. - Parameter name: The name of the table - Parameter players: The player creating the table - Parameter visible: Indicates that this is a game joinable by everyone - Returns: The table id */ func createTable(named name: TableName, player: PlayerName, visible: Bool) -> TableId { let tableId = TableId.newToken() tableNames[tableId] = name tablePlayers[tableId] = [player] playerTables[player] = tableId if visible { publicTables.insert(tableId) } return tableId } func getPublicTableInfos() -> [TableInfo] { publicTables.map { tableId in let players = tablePlayers[tableId]! let connected = players.map { playerConnections[$0] != nil } return TableInfo( id: tableId, name: tableNames[tableId]!, players: players, connected: connected) }.sorted() } func currentTableOfPlayer(named player: PlayerName) -> TableId? { playerTables[player] } /** Join a table. - Returns: The result of the join operation */ func join(tableId: TableId, player: PlayerName) -> JoinTableResult { guard var players = tablePlayers[tableId] else { return .tableNotFound } guard !players.contains(player) else { return .success } guard players.count < maximumPlayersPerTable else { return .tableIsFull } players.append(player) if let oldTable = playerTables[tableId] { remove(player: player, fromTable: oldTable) } tablePlayers[tableId] = players playerTables[tableId] = tableId return .success } func remove(player: PlayerName, fromTable tableId: TableId) { tablePlayers[tableId] = tablePlayers[tableId]?.filter { $0 != player } // TODO: End connection for removed user // TODO: End game if needed, send info to remaining players } func remove(player: PlayerName) { guard let tableId = playerTables[player] else { return } remove(player: player, fromTable: tableId) } func connect(player: PlayerName, using socket: WebSocket) -> Bool { fatalError() } func disconnect(player: PlayerName) { fatalError() } }