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.
242 lines
11 KiB
242 lines
11 KiB
//
|
|
// MatchSetupView.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 23/03/2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
import LeStorage
|
|
|
|
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 sur 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, groupStagePosition: nil, matchTypeContext: matchTypeContext, 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)
|
|
}
|
|
}
|
|
})
|
|
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")
|
|
}
|
|
}
|
|
} 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 {
|
|
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) {
|
|
//todo
|
|
if match.isSeededBy(team: team, inTeamPosition: teamPosition) {
|
|
team.bracketPosition = nil
|
|
do {
|
|
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
|
|
} catch {
|
|
Logger.error(error)
|
|
}
|
|
//match.updateTeamScores()
|
|
match.previousMatches().forEach { previousMatch in
|
|
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)
|
|
//}
|
|
|