import Foundation import WebSocketKit let numberOfCardsPerPlayer = 8 class AbstractTable where TablePlayer: Player { /// The unique id of the table let id: TableId /// The name of the table let name: TableName /// Indicates that the table is visible to all players, and can be joined by anyone let isPublic: Bool let language: SupportedLanguage = .german /** The players sitting at the table. The players are ordered clockwise around the table, with the first player starting the game. */ var players: [TablePlayer] var playedGame: GameType? { nil } init(table: ManageableTable, players: [TablePlayer]) { self.id = table.id self.name = table.name self.isPublic = table.isPublic self.players = players } init(id: TableId, name: TableName, isPublic: Bool, players: [TablePlayer]) { self.id = id self.name = name self.isPublic = isPublic self.players = players } func perform(action: PlayerAction, forPlayer name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) { (.tableStateInvalid, nil) } func play(card: Card, player name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) { (.tableStateInvalid, nil) } func cardStackPosition(ofPlayerAt index: Int) -> Int { index } func cards(forPlayerAt index: Int) -> [PlayableCard] { [] } func games(forPlayerAt index: Int) -> [GameConvertible] { [] } func gameIsSelected(byPlayerAt index: Int) -> Bool { false } func tableInfo(forPlayerAt index: Int) -> TableInfo { var info = TableInfo(id: id, name: name) info.player = playerInfo(forIndex: index)! info.playerLeft = playerInfo(forIndex: (index + 1) % 4) info.playerAcross = playerInfo(forIndex: (index + 2) % 4) info.playerRight = playerInfo(forIndex: (index + 3) % 4) info.playableGames = games(forPlayerAt: index).map { $0.id } info.actions = players[index].actions.map { $0.id } info.cards = cards(forPlayerAt: index).map { $0.cardInfo } info.playerSelectsGame = gameIsSelected(byPlayerAt: index) info.game = playedGame?.id return info } } extension AbstractTable: ManageableTable { var publicInfo: PublicTableInfo { .init(id: id, name: name, players: playerNames) } var playerNames: [PlayerName] { players.map { $0.name } } var allPlayers: [Player] { players } // MARK: Connection func connect(player name: PlayerName, using socket: WebSocket) -> Bool { guard let player = players.player(named: name) else { return false } player.connect(using: socket) sendUpdateToAllPlayers() return true } func disconnect(player name: PlayerName) { guard let player = players.player(named: name) else { return } guard player.disconnect() else { return } sendUpdateToAllPlayers() return } func sendUpdateToAllPlayers() { players.enumerated().forEach { playerIndex, player in guard player.isConnected else { return } let info = self.tableInfo(forPlayerAt: playerIndex) player.send(info) } } // MARK: Client info func playerInfo(forIndex index: Int) -> PlayerInfo? { guard let player = players.at(index) else { return nil } let height = cardStackPosition(ofPlayerAt: index) var info = player.info info.positionInTrick = height return info } func tableInfo(forPlayer player: PlayerName) -> TableInfo { let index = players.index(of: player) return tableInfo(forPlayerAt: index) } }