Schafkopf-Server/Sources/App/Model/Tables/AbstractTable.swift
2021-12-22 14:53:53 +01:00

152 lines
3.9 KiB
Swift

import Foundation
import WebSocketKit
let numberOfCardsPerPlayer = 8
class AbstractTable<TablePlayer> 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)
}
}