import Foundation import WebSocketKit typealias PlayerName = String class Player { let name: PlayerName var totalPoints: Int var socket: WebSocket? var isNextActor: Bool init(name: PlayerName, points: Int, socket: WebSocket? = nil) { self.name = name self.socket = socket self.isNextActor = false self.totalPoints = points } init(player: Player) { self.name = player.name self.socket = player.socket self.isNextActor = false self.totalPoints = player.totalPoints } var actions: [PlayerAction] { [] } var states: [PlayerState] { isConnected ? [] : [.isDisconnected] } var info: PlayerInfo { var result = PlayerInfo(name: name) result.points = totalPoints result.isConnected = isConnected result.isNextActor = isNextActor result.state = states.map { $0.rawValue } return result } } extension Player: Equatable { static func == (lhs: Player, rhs: Player) -> Bool { lhs.name == rhs.name } } extension Player { // MARK: Connection /// Indicate that the player is connected when at a table var isConnected: Bool { guard let socket = socket else { return false } guard !socket.isClosed else { self.socket = nil return false } return true } func connect(using socket: WebSocket) { _ = self.socket?.close() self.socket = socket } @discardableResult func disconnect() -> Bool { guard let socket = socket else { return false } socket.close().whenFailure { [weak self] error in log("Failed to close socket for player: \(self?.name ?? ""): \(error)") } self.socket = nil return true } @discardableResult func send(_ info: TableInfo) -> Bool { guard let socket = socket else { return false } do { try socket.send(encodeJSON(info)) } catch { log("Failed to send info: \(error)") return false } return true } // MARK: Actions func canPerform(_ action: PlayerAction) -> Bool { actions.contains(action) } } extension Player: CustomStringConvertible { var description: String { name } }