You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
13 KiB
277 lines
13 KiB
//
|
|
// MatchSetupView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 23/03/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LeStorage
|
|
import PadelClubData
|
|
|
|
struct MatchSetupView: View {
|
|
static let confirmationMessage = "Au moins une tête de série a été placée dans la branche de ce match dans les tours précédents. En plaçant une équipe ici, les équipes déjà placées dans la même branche seront retirées du tableau et devront être replacées."
|
|
|
|
@EnvironmentObject var dataStore: DataStore
|
|
|
|
@State var match: Match
|
|
@State private var seedGroup: SeedInterval?
|
|
|
|
var tournamentStore: TournamentStore? {
|
|
return match.tournamentStore
|
|
}
|
|
|
|
var matchTypeContext: MatchType {
|
|
match.matchType
|
|
}
|
|
|
|
@ViewBuilder
|
|
var body: some View {
|
|
ForEach(TeamPosition.allCases) { teamPosition in
|
|
_teamView(inTeamPosition: teamPosition)
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
func _teamView(inTeamPosition teamPosition: TeamPosition) -> some View {
|
|
let scores = match.teamScores
|
|
let team = scores.isEmpty ? nil : match.team(teamPosition)
|
|
let teamScore = (team != nil) ? scores.first(where: { $0.teamRegistration == team!.id }) : nil
|
|
let walkOutSpot = teamScore?.walkOut == 1
|
|
|
|
let shouldConfirm = match.previousMatch(teamPosition)?.isSeeded() == true
|
|
|
|
if let team, teamScore?.walkOut == nil {
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
if let teamScore, teamScore.luckyLoser != nil, match.isLoserBracket == false {
|
|
Text("Repêchée").italic().font(.caption)
|
|
}
|
|
Menu {
|
|
_removeTeam(team: team, teamPosition: teamPosition)
|
|
} label: {
|
|
TeamRowView(team: team, teamPosition: teamPosition)
|
|
}
|
|
.buttonStyle(.plain)
|
|
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
|
_removeTeam(team: team, teamPosition: teamPosition)
|
|
}
|
|
}
|
|
} else {
|
|
VStack(alignment: .leading) {
|
|
if let team {
|
|
TeamRowView(team: team, teamPosition: teamPosition)
|
|
.strikethrough()
|
|
}
|
|
HStack {
|
|
let luckyLosers = walkOutSpot ? match.luckyLosers() : []
|
|
TeamPickerView(shouldConfirm: shouldConfirm, round: match.roundObject, pickTypeContext: matchTypeContext == .bracket ? .bracket : .loserBracket, luckyLosers: luckyLosers, teamPicked: { team in
|
|
print(team.pasteData())
|
|
if walkOutSpot || team.bracketPosition != nil || matchTypeContext == .loserBracket {
|
|
match.setLuckyLoser(team: team, teamPosition: teamPosition)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
} else if team.bracketPosition == nil {
|
|
team.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
do {
|
|
try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
})
|
|
.environment(match)
|
|
if matchTypeContext == .bracket, let tournament = match.currentTournament() {
|
|
let availableQualifiedTeams = tournament.availableQualifiedTeams()
|
|
let availableSeedGroups = tournament.availableSeedGroups()
|
|
Text("ou")
|
|
Menu {
|
|
if walkOutSpot, luckyLosers.isEmpty == false {
|
|
Button {
|
|
if let randomTeam = luckyLosers.randomElement() {
|
|
match.setLuckyLoser(team: randomTeam, teamPosition: teamPosition)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} label: {
|
|
Label("Repêchage", systemImage: "dice")
|
|
}
|
|
}
|
|
|
|
if availableQualifiedTeams.isEmpty == false {
|
|
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
|
|
if let randomTeam = availableQualifiedTeams.randomElement() {
|
|
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
do {
|
|
try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} label: {
|
|
Label("Qualifié sortant", systemImage: "dice")
|
|
}
|
|
}
|
|
|
|
ForEach(availableSeedGroups, id: \.self) { seedGroup in
|
|
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
|
|
if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
|
|
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
do {
|
|
try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} label: {
|
|
Label(seedGroup.localizedInterval(), systemImage: "dice")
|
|
}
|
|
}
|
|
|
|
Divider()
|
|
|
|
Menu {
|
|
ForEach(tournament.availableSeedGroups(includeAll: true), id: \.self) { seedGroup in
|
|
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
|
|
if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
|
|
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
do {
|
|
try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} label: {
|
|
Label(seedGroup.localizedInterval(), systemImage: "dice")
|
|
}
|
|
}
|
|
} label: {
|
|
Text("plus d'options")
|
|
}
|
|
|
|
} label: {
|
|
Text("Tirer au sort").tag(nil as SeedInterval?)
|
|
.underline()
|
|
}
|
|
.disabled(availableSeedGroups.isEmpty && walkOutSpot == false && availableQualifiedTeams.isEmpty)
|
|
|
|
if matchTypeContext == .bracket {
|
|
Spacer()
|
|
if match.isSeedLocked(atTeamPosition: teamPosition) {
|
|
Button {
|
|
match.unlockSeedPosition(atTeamPosition: teamPosition)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
} label: {
|
|
Text("Libérer")
|
|
.underline()
|
|
}
|
|
} else if match.isFromLastRound() == false {
|
|
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
|
|
_ = match.lockAndGetSeedPosition(atTeamPosition: teamPosition)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
} label: {
|
|
Text("Réserver")
|
|
.underline()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.fixedSize(horizontal: false, vertical: true)
|
|
.buttonStyle(.borderless)
|
|
}
|
|
}
|
|
}
|
|
|
|
func _removeTeam(team: TeamRegistration, teamPosition: TeamPosition) -> some View {
|
|
Button(role: .cancel) {
|
|
if match.isSeededBy(team: team, inTeamPosition: teamPosition) {
|
|
if let score = match.teamScore(ofTeam: team) {
|
|
do {
|
|
try tournamentStore?.teamScores.delete(instance: score)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
|
|
team.bracketPosition = nil
|
|
do {
|
|
try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
if let previousMatch = match.previousMatch(teamPosition) {
|
|
if previousMatch.disabled {
|
|
previousMatch.enableMatch()
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: previousMatch)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
}
|
|
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
} else if match.isLoserBracket {
|
|
if let score = match.teamScore(ofTeam: team) {
|
|
do {
|
|
try tournamentStore?.teamScores.delete(instance: score)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} else {
|
|
match.teamWillBeWalkOut(team)
|
|
do {
|
|
try tournamentStore?.matches.addOrUpdate(instance: match)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
}
|
|
} label: {
|
|
Label("retirer", systemImage: "xmark")
|
|
}
|
|
}
|
|
}
|
|
|
|
//#Preview {
|
|
// MatchSetupView(match: Match.mock())
|
|
// .environmentObject(DataStore.shared)
|
|
//}
|
|
|