From ac3ca1f6512ec7634a68e98603897a8a1df898a3 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Thu, 27 Jun 2024 15:57:21 +0200 Subject: [PATCH] b76 --- PadelClub.xcodeproj/project.pbxproj | 4 +- PadelClub/Data/Tournament.swift | 33 +++++++++++++--- .../GroupStage/GroupStageSettingsView.swift | 38 ++++++++++++++++++ PadelClub/Views/Round/RoundSettingsView.swift | 39 +++++++++++++++++++ PadelClub/Views/Round/RoundsView.swift | 2 +- .../Screen/InscriptionManagerView.swift | 28 ++++++++----- 6 files changed, 126 insertions(+), 18 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index d4e011c..7e3feab 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1882,7 +1882,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 75; + CURRENT_PROJECT_VERSION = 76; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; @@ -1922,7 +1922,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 75; + CURRENT_PROJECT_VERSION = 76; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 70e79b8..648ca9b 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -550,12 +550,7 @@ defer { } func groupStageSpots() -> Int { - let _groupStagesCount = groupStages().count - if groupStageCount != _groupStagesCount { - return groupStageCount * teamsPerGroupStage - } else { - return groupStages().map { $0.size }.reduce(0,+) - } + return groupStages().map { $0.size }.reduce(0,+) } func seeds() -> [TeamRegistration] { @@ -1853,6 +1848,32 @@ defer { } + typealias TeamPlacementIssue = (shouldBeInIt: [String], shouldNotBeInIt: [String]) + func groupStageTeamPlacementIssue() -> TeamPlacementIssue { + let selected = selectedSortedTeams() + let allTeams = unsortedTeams() + let newGroup = selected.suffix(groupStageSpots()) + let currentGroup = allTeams.filter({ $0.groupStagePosition != nil }) + let selectedIds = newGroup.map { $0.id } + let groupIds = currentGroup.map { $0.id } + let shouldBeInIt = Set(selectedIds).subtracting(groupIds) + let shouldNotBeInIt = Set(groupIds).subtracting(selectedIds) + return (Array(shouldBeInIt), Array(shouldNotBeInIt)) + } + + func bracketTeamPlacementIssue() -> TeamPlacementIssue { + let selected = selectedSortedTeams() + let allTeams = unsortedTeams() + let seedCount = max(selected.count - groupStageSpots(), 0) + let newGroup = selected.prefix(seedCount) + let currentGroup = allTeams.filter({ $0.bracketPosition != nil }) + let selectedIds = newGroup.map { $0.id } + let groupIds = currentGroup.map { $0.id } + let shouldBeInIt = Set(selectedIds).subtracting(groupIds) + let shouldNotBeInIt = Set(groupIds).subtracting(selectedIds) + return (Array(shouldBeInIt), Array(shouldNotBeInIt)) + } + // MARK: - func insertOnServer() throws { diff --git a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift index bbff2e4..a2feafc 100644 --- a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift +++ b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift @@ -18,6 +18,44 @@ struct GroupStageSettingsView: View { if tournament.shouldVerifyGroupStage { Section { + let issues = tournament.groupStageTeamPlacementIssue() + DisclosureGroup { + ForEach(issues.shouldBeInIt, id: \.self) { id in + if let team: TeamRegistration = Store.main.findById(id) { + TeamRowView(team: team) + } + } + } label: { + LabeledContent { + Text(issues.shouldBeInIt.count.formatted()) + } label: { + Text("Équipes à mettre en poule") + } + } + DisclosureGroup { + ForEach(issues.shouldNotBeInIt, id: \.self) { id in + if let team = dataStore.teamRegistrations.findById(id) { + Menu { + Button("Retirer de sa poule") { + team.resetGroupeStagePosition() + do { + try dataStore.teamRegistrations.addOrUpdate(instance: team) + } catch { + Logger.error(error) + } + } + } label: { + TeamRowView(team: team) + } + } + } + } label: { + LabeledContent { + Text(issues.shouldNotBeInIt.count.formatted()) + } label: { + Text("Équipes à retirer des poules") + } + } RowButtonView("Valider les poules en l'état", role: .destructive) { tournament.shouldVerifyGroupStage = false do { diff --git a/PadelClub/Views/Round/RoundSettingsView.swift b/PadelClub/Views/Round/RoundSettingsView.swift index 51b87dc..f9f20dd 100644 --- a/PadelClub/Views/Round/RoundSettingsView.swift +++ b/PadelClub/Views/Round/RoundSettingsView.swift @@ -17,6 +17,45 @@ struct RoundSettingsView: View { List { if tournament.shouldVerifyBracket { Section { + let issues = tournament.bracketTeamPlacementIssue() + DisclosureGroup { + ForEach(issues.shouldBeInIt, id: \.self) { id in + if let team: TeamRegistration = Store.main.findById(id) { + TeamRowView(team: team) + } + } + } label: { + LabeledContent { + Text(issues.shouldBeInIt.count.formatted()) + } label: { + Text("Équipes à mettre dans le tableau") + } + } + DisclosureGroup { + ForEach(issues.shouldNotBeInIt, id: \.self) { id in + if let team = dataStore.teamRegistrations.findById(id) { + Menu { + Button("Retirer du tableau") { + team.resetBracketPosition() + do { + try dataStore.teamRegistrations.addOrUpdate(instance: team) + } catch { + Logger.error(error) + } + } + } label: { + TeamRowView(team: team) + } + } + } + } label: { + LabeledContent { + Text(issues.shouldNotBeInIt.count.formatted()) + } label: { + Text("Équipes à retirer du tableau") + } + } + RowButtonView("Valider l'état du tableau", role: .destructive) { tournament.shouldVerifyBracket = false do { diff --git a/PadelClub/Views/Round/RoundsView.swift b/PadelClub/Views/Round/RoundsView.swift index 913893e..db02f53 100644 --- a/PadelClub/Views/Round/RoundsView.swift +++ b/PadelClub/Views/Round/RoundsView.swift @@ -19,7 +19,7 @@ struct RoundsView: View { let _destinations = tournament.rounds().map { UpperRound(round: $0) } self.destinations = _destinations let availableSeeds = tournament.availableSeeds() - if tournament.shouldVerifyBracket && availableSeeds.isEmpty { + if tournament.shouldVerifyBracket { _selectedRound = State(wrappedValue: nil) } else { _selectedRound = State(wrappedValue: _destinations.first(where: { $0.id == tournament.getActiveRound()?.id })) diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index ad5b8ca..2abf66d 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -56,7 +56,6 @@ struct InscriptionManagerView: View { @State private var showSubscriptionView: Bool = false @State private var registrationIssues: Int? = nil @State private var sortedTeams: [TeamRegistration] = [] - @State private var unfilteredTeams: [TeamRegistration] = [] @State private var walkoutTeams: [TeamRegistration] = [] @State private var unsortedTeamsWithoutWO: [TeamRegistration] = [] @State private var unsortedPlayers: [PlayerRegistration] = [] @@ -118,7 +117,6 @@ struct InscriptionManagerView: View { private func _clearScreen() { teamPaste = nil unsortedPlayers.removeAll() - unfilteredTeams.removeAll() walkoutTeams.removeAll() unsortedTeamsWithoutWO.removeAll() sortedTeams.removeAll() @@ -181,7 +179,7 @@ struct InscriptionManagerView: View { _managementView() if _isEditingTeam() { _buildingTeamView() - } else if unfilteredTeams.isEmpty { + } else if sortedTeams.isEmpty { _inscriptionTipsView() } else { _teamRegisteredView() @@ -326,6 +324,15 @@ struct InscriptionManagerView: View { UpdateSourceRankDateView(currentRankSourceDate: $currentRankSourceDate, confirmUpdateRank: $confirmUpdateRank, tournament: tournament) .tint(.master) } + .onChange(of: filterMode) { + _prepareTeams() + } + .onChange(of: sortingMode) { + _prepareTeams() + } + .onChange(of: byDecreasingOrdering) { + _prepareTeams() + } .toolbar { if _isEditingTeam() { ToolbarItem(placement: .cancellationAction) { @@ -454,6 +461,9 @@ struct InscriptionManagerView: View { } #endif sortedTeams = tournament.sortedTeams() + } + + var filteredTeams: [TeamRegistration] { var teams = sortedTeams if filterMode == .walkOut { @@ -465,9 +475,9 @@ struct InscriptionManagerView: View { } if byDecreasingOrdering { - self.unfilteredTeams = teams.reversed() + return teams.reversed() } else { - self.unfilteredTeams = teams + return teams } } @@ -496,10 +506,10 @@ struct InscriptionManagerView: View { if presentSearch == false { _rankHandlerView() _relatedTips() - _informationView(count: unfilteredTeams.count) + _informationView() } - let teams = searchField.isEmpty ? unfilteredTeams : unfilteredTeams.filter({ $0.contains(searchField.canonicalVersion) }) + let teams = searchField.isEmpty ? filteredTeams : filteredTeams.filter({ $0.contains(searchField.canonicalVersion) }) if teams.isEmpty && searchField.isEmpty == false { ContentUnavailableView { @@ -710,7 +720,7 @@ struct InscriptionManagerView: View { } } - private func _informationView(count: Int) -> some View { + private func _informationView() -> some View { Section { LabeledContent { Text(unsortedTeamsWithoutWO.count.formatted() + "/" + tournament.teamCount.formatted()).font(.largeTitle) @@ -872,7 +882,7 @@ struct InscriptionManagerView: View { private func _isDuplicate() -> Bool { let ids : [String?] = _currentSelectionIds() - if unfilteredTeams.anySatisfy({ $0.containsExactlyPlayerLicenses(ids) }) { + if sortedTeams.anySatisfy({ $0.containsExactlyPlayerLicenses(ids) }) { return true } return false