diff --git a/PadelClub/Data/Event.swift b/PadelClub/Data/Event.swift index 85baf07..21a0d91 100644 --- a/PadelClub/Data/Event.swift +++ b/PadelClub/Data/Event.swift @@ -32,7 +32,12 @@ final class Event: ModelObject, Storable { } override func deleteDependencies() throws { - DataStore.shared.tournaments.deleteDependencies(self.tournaments) + let tournaments = self.tournaments + for tournament in tournaments { + try tournament.deleteDependencies() + } + + DataStore.shared.tournaments.deleteDependencies(tournaments) DataStore.shared.dateIntervals.deleteDependencies(self.courtsUnavailability) } diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index 26d44a0..cba7fb4 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -381,7 +381,11 @@ final class GroupStage: ModelObject, Storable { } override func deleteDependencies() throws { - self.tournamentStore.matches.deleteDependencies(self._matches()) + let matches = self._matches() + for match in matches { + try match.deleteDependencies() + } + self.tournamentStore.matches.deleteDependencies(matches) } func encode(to encoder: Encoder) throws { diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index 5d4c536..fb20842 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -78,7 +78,11 @@ final class Match: ModelObject, Storable { guard let tournament = self.currentTournament() else { return } - tournament.tournamentStore.teamScores.deleteDependencies(self.teamScores) + let teamScores = self.teamScores + for teamScore in teamScores { + try teamScore.deleteDependencies() + } + tournament.tournamentStore.teamScores.deleteDependencies(teamScores) } func indexInRound(in matches: [Match]? = nil) -> Int { diff --git a/PadelClub/Data/Round.swift b/PadelClub/Data/Round.swift index e10816b..31e805c 100644 --- a/PadelClub/Data/Round.swift +++ b/PadelClub/Data/Round.swift @@ -455,12 +455,12 @@ defer { return nextRound()?.isRankDisabled() == false } - func seedInterval(expanded: Bool = false) -> SeedInterval? { + func seedInterval(initialMode: Bool = false) -> SeedInterval? { #if DEBUG_TIME //DEBUGING TIME let start = Date() defer { let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000) - print("func seedInterval(expanded: Bool = false)", duration.formatted(.units(allowed: [.seconds, .milliseconds]))) + print("func seedInterval(initialMode)", initialMode, duration.formatted(.units(allowed: [.seconds, .milliseconds]))) } #endif @@ -477,24 +477,24 @@ defer { } if let previousRound = previousRound() { - if previousRound.enabledMatches().isEmpty == false && expanded == false { - return previousRound.seedInterval()?.chunks()?.first + if (previousRound.enabledMatches().isEmpty == false || initialMode) { + return previousRound.seedInterval(initialMode: initialMode)?.chunks()?.first } else { - return previousRound.previousRound()?.seedInterval() + return previousRound.previousRound()?.seedInterval(initialMode: initialMode) } } else if let parentRound { - if parentRound.parent == nil && expanded == false { - return parentRound.seedInterval() + if parentRound.parent == nil { + return parentRound.seedInterval(initialMode: initialMode) } - return parentRound.seedInterval()?.chunks()?.last + return parentRound.seedInterval(initialMode: initialMode)?.chunks()?.last } return nil } - func roundTitle(_ displayStyle: DisplayStyle = .wide) -> String { + func roundTitle(_ displayStyle: DisplayStyle = .wide, initialMode: Bool = false) -> String { if parent != nil { - if let seedInterval = seedInterval() { + if let seedInterval = seedInterval(initialMode: initialMode) { return seedInterval.localizedLabel(displayStyle) } print("Round pas trouvé", id, parent, index) @@ -574,7 +574,8 @@ defer { let matches = (0.. String { - let range = [tournamentLevel.points(for: last - 1 - reduce, count: teamsCount), - tournamentLevel.points(for: first - 1 - reduce, count: teamsCount)] + let range = [tournamentLevel.points(for: last - 1, count: teamsCount), + tournamentLevel.points(for: first - 1, count: teamsCount)] return range.map { $0.formatted(.number.sign(strategy: .always())) }.joined(separator: " / ") + " pts" } @@ -38,32 +37,24 @@ struct SeedInterval: Hashable, Comparable { if dimension > 3 { let split = dimension / 2 if split%2 == 0 { - let firstHalf = SeedInterval(first: first, last: first + split - 1, reduce: reduce) - let secondHalf = SeedInterval(first: first + split, last: last, reduce: reduce) + let firstHalf = SeedInterval(first: first, last: first + split - 1) + let secondHalf = SeedInterval(first: first + split, last: last) return [firstHalf, secondHalf] } else { - let firstHalf = SeedInterval(first: first, last: first + split, reduce: reduce) - let secondHalf = SeedInterval(first: first + split + 1, last: last, reduce: reduce) + let firstHalf = SeedInterval(first: first, last: first + split) + let secondHalf = SeedInterval(first: first + split + 1, last: last) return [firstHalf, secondHalf] } } else { return nil } } - - var computedLast: Int { - last - reduce - } - - var computedFirst: Int { - first - reduce - } - + func localizedLabel(_ displayStyle: DisplayStyle = .wide) -> String { if dimension < 2 { - return "#\(first - reduce) / #\(last - reduce)" + return "#\(first) / #\(last)" } else { - return "#\(first - reduce) à #\(last - reduce)" + return "#\(first) à #\(last)" } } } diff --git a/PadelClub/Views/Components/FortuneWheelView.swift b/PadelClub/Views/Components/FortuneWheelView.swift index c30c919..ab8314a 100644 --- a/PadelClub/Views/Components/FortuneWheelView.swift +++ b/PadelClub/Views/Components/FortuneWheelView.swift @@ -62,26 +62,29 @@ struct SpinDrawView: View { let drawees: [any SpinDrawable] @State var segments: [any SpinDrawable] var autoMode: Bool = false - let completion: ([DrawResult]) async -> Void // Completion closure + let completion: ([DrawResult]) -> Void // Completion closure @State private var drawCount: Int = 0 @State private var draws: [DrawResult] = [DrawResult]() @State private var drawOptions: [DrawOption] = [DrawOption]() @State private var selectedIndex: Int? @State private var disabled: Bool = false + @State private var validating: Bool = false + + var scrollDisabled: Bool { + drawCount < drawees.count || selectedIndex != nil + } var body: some View { List { if selectedIndex != nil { Section { - _validationLabelView(drawee: drawCount, result: segments[draws.last!.drawIndex]) + _validationLabelView(drawee: drawCount, result: segments[draws.last!.drawIndex]) if autoMode == false || drawCount == drawees.count { RowButtonView("Valider le tirage") { - await completion(draws) + completion(draws) dismiss() } - } else { - Text("Prochain tirage en préparation") } } } else if drawCount < drawees.count { @@ -135,16 +138,17 @@ struct SpinDrawView: View { } } } else { - Section { - Text("Tous les tirages sont terminés") - ForEach(draws) { drawResult in + ForEach(draws) { drawResult in + Section { _validationLabelView(drawee: drawResult.drawee, result: segments[drawResult.drawIndex]) } } - RowButtonView("Valider les tirages") { - await completion(draws) - dismiss() + Section { + RowButtonView("Valider les tirages") { + await completion(draws) + dismiss() + } } } @@ -164,6 +168,22 @@ struct SpinDrawView: View { } .disabled(disabled || autoMode) } + + if scrollDisabled == false { + ToolbarItem(placement: .topBarTrailing) { + Button { + validating = true + completion(draws) + dismiss() + } label: { + Text("Tout valider") + } + } + + ToolbarItem(placement: .status) { + Text("Tous les tirages sont terminés") + } + } } .navigationBarBackButtonHidden() .navigationTitle("Tirage au sort") @@ -171,7 +191,7 @@ struct SpinDrawView: View { .toolbarBackground(.visible, for: .navigationBar) .toolbar(.hidden, for: .tabBar) .listStyle(.insetGrouped) - .scrollDisabled(true) + .scrollDisabled(scrollDisabled) .interactiveDismissDisabled() .onAppear { for (index, segment) in segments.enumerated() { diff --git a/PadelClub/Views/Round/RoundView.swift b/PadelClub/Views/Round/RoundView.swift index c4c43ce..e848e55 100644 --- a/PadelClub/Views/Round/RoundView.swift +++ b/PadelClub/Views/Round/RoundView.swift @@ -28,7 +28,7 @@ struct RoundView: View { return self.tournament.tournamentStore } - private func _getAvailableSeedGroup() async { + private func _getAvailableSeedGroup() { #if DEBUG_TIME //DEBUGING TIME let start = Date() defer { @@ -40,7 +40,7 @@ struct RoundView: View { availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: upperRound.round.index) } - private func _getSpaceLeft() async { + private func _getSpaceLeft() { #if DEBUG_TIME //DEBUGING TIME let start = Date() defer { @@ -130,12 +130,11 @@ struct RoundView: View { Section { RowButtonView("Placer \(availableSeedGroup.localizedLabel())" + ((availableSeedGroup.isFixed() == false) ? " au hasard" : "")) { tournament.setSeeds(inRoundIndex: upperRound.round.index, inSeedGroup: availableSeedGroup) - await _save() + _save() if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { self.isEditingTournamentSeed.wrappedValue = false } - await _getSpaceLeft() - await _getAvailableSeedGroup() + _prepareRound() } } footer: { if availableSeedGroup.isFixed() == false { @@ -161,17 +160,14 @@ struct RoundView: View { ForEach(availableQualifiedTeams) { team in NavigationLink { SpinDrawView(drawees: [team], segments: spaceLeft) { results in - Task { - results.forEach { drawResult in - team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) - } - await _save() - if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { - self.isEditingTournamentSeed.wrappedValue = false - } - await _getSpaceLeft() - await _getAvailableSeedGroup() + results.forEach { drawResult in + team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) } + _save() + if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { + self.isEditingTournamentSeed.wrappedValue = false + } + _prepareRound() } } label: { TeamRowView(team: team, displayCallDate: false) @@ -193,17 +189,14 @@ struct RoundView: View { ForEach(availableSeeds) { team in NavigationLink { SpinDrawView(drawees: [team], segments: seedSpaceLeft) { results in - Task { - results.forEach { drawResult in - team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false) - } - await _save() - if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { - self.isEditingTournamentSeed.wrappedValue = false - } - await _getSpaceLeft() - await _getAvailableSeedGroup() + results.forEach { drawResult in + team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false) + } + _save() + if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { + self.isEditingTournamentSeed.wrappedValue = false } + _prepareRound() } } label: { TeamRowView(team: team, displayCallDate: false) @@ -221,17 +214,14 @@ struct RoundView: View { ForEach(availableSeeds) { team in NavigationLink { SpinDrawView(drawees: [team], segments: spaceLeft) { results in - Task { - results.forEach { drawResult in - team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) - } - await _save() - if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { - self.isEditingTournamentSeed.wrappedValue = false - } - await _getSpaceLeft() - await _getAvailableSeedGroup() + results.forEach { drawResult in + team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) } + _save() + if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { + self.isEditingTournamentSeed.wrappedValue = false + } + _prepareRound() } } label: { TeamRowView(team: team, displayCallDate: false) @@ -283,9 +273,7 @@ struct RoundView: View { PrintSettingsView(tournament: tournament) } .onAppear { - Task { - await _prepareRound() - } + _prepareRound() let seeds = upperRound.round.seeds() SlideToDeleteSeedTip.seeds = seeds.count PrintTip.seeds = seeds.count @@ -294,17 +282,19 @@ struct RoundView: View { .fullScreenCover(isPresented: showVisualDrawView) { if let availableSeedGroup = selectedSeedGroup { let seeds = tournament.seeds(inSeedGroup: availableSeedGroup) - let availableSeedSpot = tournament.availableSeedSpot(inRoundIndex: upperRound.round.index) + let opposingSeeding = seedSpaceLeft.isEmpty ? true : false + let availableSeedSpot = opposingSeeding ? spaceLeft : seedSpaceLeft NavigationStack { SpinDrawView(drawees: seeds, segments: availableSeedSpot, autoMode: true) { draws in - Task { - draws.forEach { drawResult in - seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: false) - } - await _save() - if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { - self.isEditingTournamentSeed.wrappedValue = false - } + draws.forEach { drawResult in + seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: opposingSeeding) + } + + _save() + _prepareRound() + + if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty { + self.isEditingTournamentSeed.wrappedValue = false } } } @@ -315,9 +305,7 @@ struct RoundView: View { ToolbarItem(placement: .topBarTrailing) { Button(isEditingTournamentSeed.wrappedValue == true ? "Valider" : "Modifier") { if isEditingTournamentSeed.wrappedValue == true { - Task { - await _save() - } + _save() } isEditingTournamentSeed.wrappedValue.toggle() } @@ -325,7 +313,7 @@ struct RoundView: View { } } - private func _save() async { + private func _save() { do { try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams()) } catch { @@ -348,13 +336,9 @@ struct RoundView: View { } } - private func _prepareRound() async { - Task { - await _getSpaceLeft() - } - Task { - await _getAvailableSeedGroup() - } + private func _prepareRound() { + _getSpaceLeft() + _getAvailableSeedGroup() } }