Schafkopf-Server/Sources/App/Model/Tables/FinishedTable.swift

160 lines
4.7 KiB
Swift
Raw Normal View History

2021-12-18 15:08:43 +01:00
import Foundation
2022-10-18 11:40:08 +02:00
import Fluent
2021-12-18 15:08:43 +01:00
final class FinishedTable: AbstractTable<FinishedPlayer> {
let game: GameType
2021-12-21 14:24:53 +01:00
let totalNumberOfDoubles: Int
let leadingTrumps: Int
2021-12-22 15:06:24 +01:00
/// Required for the last cards on the table
let indexOfTrickStarter: Int
2021-12-21 14:24:53 +01:00
var cost: Int {
guard !isBettel else {
return game.basicCost * 2^^totalNumberOfDoubles
}
var cost = game.basicCost
if isSchwarz {
cost += 10
} else if isSchneider {
cost += 5
}
cost += 5 * leadingTrumps
2021-12-22 14:54:31 +01:00
guard game != .hochzeit else {
// Wedding is doubled
return cost * 2^^(totalNumberOfDoubles + 1)
}
2021-12-21 14:24:53 +01:00
return cost * 2^^totalNumberOfDoubles
2021-12-18 15:08:43 +01:00
}
2021-12-21 14:24:53 +01:00
var gameSelector: FinishedPlayer {
players.first { $0.selectedGame }!
2021-12-18 15:08:43 +01:00
}
2021-12-21 14:24:53 +01:00
let selectorDidWin: Bool
2021-12-18 15:08:43 +01:00
2021-12-21 14:24:53 +01:00
var coPlayers: [FinishedPlayer] {
let selector = gameSelector
return players.filter { $0 != selector && $0.leadsGame == selector.leadsGame }
2021-12-18 15:08:43 +01:00
}
2021-12-21 14:24:53 +01:00
var winners: [FinishedPlayer] {
let selectorLeads = gameSelector.leadsGame
return players.filter { $0.leadsGame == (selectorDidWin == selectorLeads) }
2021-12-18 15:08:43 +01:00
}
2021-12-21 14:24:53 +01:00
var selectorTeamPoints: Int {
gameSelector.points + coPlayers.map { $0.points }.reduce(0, +)
2021-12-18 15:08:43 +01:00
}
2021-12-21 14:24:53 +01:00
var isBettel: Bool {
game == .bettel
2021-12-18 15:08:43 +01:00
}
2021-12-22 14:54:31 +01:00
var isHochzeit: Bool {
game == .hochzeit
}
2021-12-18 15:08:43 +01:00
var isSchwarz: Bool {
2021-12-21 14:24:53 +01:00
!isBettel && (selectorTeamPoints == 0 || selectorTeamPoints == 120)
2021-12-18 15:08:43 +01:00
}
var isSchneider: Bool {
2021-12-21 14:24:53 +01:00
guard !isBettel else {
return false
}
let points = selectorTeamPoints
let leads = gameSelector.leadsGame
let limit = leads ? 31 : 30
return points < limit || 120 - points < limit
2021-12-18 15:08:43 +01:00
}
override var playedGame: GameType? {
game
}
init(table: PlayingTable) {
let players = table.players.map(FinishedPlayer.init)
2021-12-21 14:24:53 +01:00
let selector = table.players.first { $0.selectsGame }!
2021-12-18 15:08:43 +01:00
self.game = table.game
2021-12-21 14:24:53 +01:00
self.totalNumberOfDoubles = table.totalNumberOfDoubles
2021-12-22 15:06:24 +01:00
self.indexOfTrickStarter = table.indexOfTrickStarter
2021-12-21 14:24:53 +01:00
defer {
for player in winners {
player.isNextActor = true
}
}
guard table.game != .bettel else {
self.selectorDidWin = selector.wonTricks.isEmpty
self.leadingTrumps = 0
super.init(table: table, players: players)
return
}
let selectorLeads = selector.leadsGame
let teamPoints = players
.filter { $0.leadsGame == selectorLeads }
.map { $0.points }
2021-12-18 15:08:43 +01:00
.reduce(0, +)
2021-12-21 14:24:53 +01:00
self.selectorDidWin = teamPoints > (selectorLeads ? 60 : 59)
self.leadingTrumps = table.leadingTrumps
2021-12-18 15:08:43 +01:00
super.init(table: table, players: players)
}
/**
Perform a deal action on the finished table.
- Parameter action: The action to perform
- Parameter player: The name of the player
*/
override func perform(action: PlayerAction, forPlayer name: PlayerName) -> (result: PlayerActionResult, table: ManageableTable?) {
// Only dealing is allowed...
guard action == .deal else {
return (.tableStateInvalid, nil)
}
guard let player = players.player(named: name) else {
2023-02-06 22:03:02 +01:00
log("Unexpectedly missing player \(name) for deal action at finished table \(self.name)")
2021-12-18 15:08:43 +01:00
return (.tableStateInvalid, nil)
}
guard player.canPerform(.deal) else {
2023-02-06 22:03:02 +01:00
log("Finished table: Player \(name) can't perform deal")
2021-12-18 15:08:43 +01:00
return (.tableStateInvalid, nil)
}
let waiting = WaitingTable(oldTableAdvancedByOne: self)
let table = DealingTable(table: waiting)
return (.success, table)
}
2021-12-21 09:53:42 +01:00
override func tableInfo(forPlayerAt index: Int) -> TableInfo {
var info = super.tableInfo(forPlayerAt: index)
2021-12-21 11:16:54 +01:00
info.summary = GameSummary(table: self, language: language)
2021-12-21 09:53:42 +01:00
return info
}
2021-12-22 15:06:24 +01:00
override func cardStackPosition(ofPlayerAt index: Int) -> Int {
(4 + index - indexOfTrickStarter) % 4
}
2022-10-18 11:40:08 +02:00
func updatePlayerPoints(in database: Database) async throws {
let points = cost
let winnerNames = winners.map { $0.name }
for player in allPlayers {
guard let user = try await User.query(on: database).filter(\.$name == player.name).first() else {
continue
}
if winnerNames.contains(player.name) {
user.points += points
player.totalPoints += points
} else {
user.points -= points
player.totalPoints -= points
}
try await user.save(on: database)
}
}
2021-12-18 15:08:43 +01:00
}