From 119d7e53c9825637d81f64629dcc58fe614e9c80 Mon Sep 17 00:00:00 2001 From: Raz Date: Thu, 20 Feb 2025 10:59:31 +0100 Subject: [PATCH] fix wildcard management fix p500 dates and schedule add format aide memoire optimize selectedsorted teams calls --- PadelClub.xcodeproj/project.pbxproj | 12 +- PadelClub/Data/TeamRegistration.swift | 8 +- PadelClub/Data/Tournament.swift | 26 ++-- PadelClub/Utils/PadelRule.swift | 34 +++-- PadelClub/Views/Calling/SendToAllView.swift | 7 +- .../Toolbox/MatchFormatStorageView.swift | 2 +- .../Views/Planning/MatchFormatGuideView.swift | 72 +++++++++++ .../Views/Planning/PlanningSettingsView.swift | 25 +++- .../Team/Components/TeamWeightView.swift | 7 +- PadelClub/Views/Team/EditingTeamView.swift | 3 +- PadelClub/Views/Team/TeamRowView.swift | 3 +- .../Views/Tournament/FileImportView.swift | 2 +- .../TournamentMatchFormatsSettingsView.swift | 2 +- .../Screen/InscriptionManagerView.swift | 121 +++++++++--------- 14 files changed, 221 insertions(+), 103 deletions(-) create mode 100644 PadelClub/Views/Planning/MatchFormatGuideView.swift diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index 6fbfa92..e1b24d3 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -798,6 +798,9 @@ FFA6D7852BB0B795003A31F3 /* FileImportManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7842BB0B795003A31F3 /* FileImportManager.swift */; }; FFA6D7872BB0B7A2003A31F3 /* CloudConvert.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */; }; FFB1C98B2C10255100B154A7 /* TournamentBroadcastRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */; }; + FFB378342D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; }; + FFB378352D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; }; + FFB378362D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */; }; FFB9C8712BBADDE200A0EF4F /* Selectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8702BBADDE200A0EF4F /* Selectable.swift */; }; FFB9C8752BBADDF700A0EF4F /* SeedInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */; }; FFBA2D2D2CA2CE9E00D5BBDD /* CodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C33F752C9B1EC5006316DE /* CodingContainer+Extensions.swift */; }; @@ -1201,6 +1204,7 @@ FFA6D7862BB0B7A2003A31F3 /* CloudConvert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudConvert.swift; sourceTree = ""; }; FFA6D78A2BB0BEB3003A31F3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; FFB1C98A2C10255100B154A7 /* TournamentBroadcastRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentBroadcastRowView.swift; sourceTree = ""; }; + FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchFormatGuideView.swift; sourceTree = ""; }; FFB9C8702BBADDE200A0EF4F /* Selectable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Selectable.swift; sourceTree = ""; }; FFB9C8742BBADDF700A0EF4F /* SeedInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedInterval.swift; sourceTree = ""; }; FFBE62042CE9DA0900815D33 /* MatchViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchViewStyle.swift; sourceTree = ""; }; @@ -2073,6 +2077,7 @@ FFF527D52BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift */, FFF9645A2BC2D53B00EEF017 /* GroupStageScheduleEditorView.swift */, FFF116E22BD2AF4800A33B06 /* CourtAvailabilitySettingsView.swift */, + FFB378332D672ED100EE82E9 /* MatchFormatGuideView.swift */, FF1162882BD0523B000C4809 /* Components */, ); path = Planning; @@ -2494,6 +2499,7 @@ FFBFC3962CF05CBB000EBD8D /* DateMenuView.swift in Sources */, FF089EBB2BB0120700F0AEC7 /* PlayerPopoverView.swift in Sources */, FF70916E2B9108C600AB08DA /* InscriptionManagerView.swift in Sources */, + FFB378352D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */, FF77CE542CCCD1B200CBCBB4 /* MatchFormatPickingView.swift in Sources */, FF82CFC92B9132AF00B0CAF2 /* ActivityView.swift in Sources */, FFDB1C732BB2CFE900F1E467 /* MySortDescriptor.swift in Sources */, @@ -2785,6 +2791,7 @@ FFBFC3972CF05CBB000EBD8D /* DateMenuView.swift in Sources */, FF4CBFDA2C996C0600151637 /* PlayerPopoverView.swift in Sources */, FF4CBFDB2C996C0600151637 /* InscriptionManagerView.swift in Sources */, + FFB378362D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */, FF77CE522CCCD1B200CBCBB4 /* MatchFormatPickingView.swift in Sources */, FF4CBFDC2C996C0600151637 /* ActivityView.swift in Sources */, FF4CBFDD2C996C0600151637 /* MySortDescriptor.swift in Sources */, @@ -3055,6 +3062,7 @@ FFBFC3952CF05CBB000EBD8D /* DateMenuView.swift in Sources */, FF70FB592C90584900129CC2 /* PlayerPopoverView.swift in Sources */, FF70FB5A2C90584900129CC2 /* InscriptionManagerView.swift in Sources */, + FFB378342D672ED200EE82E9 /* MatchFormatGuideView.swift in Sources */, FF77CE532CCCD1B200CBCBB4 /* MatchFormatPickingView.swift in Sources */, FF70FB5B2C90584900129CC2 /* ActivityView.swift in Sources */, FF70FB5C2C90584900129CC2 /* MySortDescriptor.swift in Sources */, @@ -3315,7 +3323,6 @@ DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; - GCC_OPTIMIZATION_LEVEL = 0; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PadelClub/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Padel Club"; @@ -3344,7 +3351,6 @@ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -3362,7 +3368,6 @@ DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; - GCC_OPTIMIZATION_LEVEL = 0; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PadelClub/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Padel Club"; @@ -3391,7 +3396,6 @@ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index cc7dd6d..e9337af 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -632,13 +632,17 @@ final class TeamRegistration: ModelObject, Storable { func isDifferentPosition(_ drawMatchIndex: Int?) -> Bool { if let bracketPosition, let drawMatchIndex { return drawMatchIndex != bracketPosition - } else if let bracketPosition { + } else if bracketPosition != nil { return true - } else if let drawMatchIndex { + } else if drawMatchIndex != nil { return true } return false } + + func shouldDisplayRankAndWeight() -> Bool { + unsortedPlayers().count > 0 + } enum CodingKeys: String, CodingKey { case _id = "id" diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 20c1a44..4470155 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -428,6 +428,11 @@ final class Tournament : ModelObject, Storable { return Array(self.tournamentStore.teamRegistrations) } + func unsortedTeamsCount() -> Int { + return self.tournamentStore.teamRegistrations.count + } + + func groupStages(atStep step: Int = 0) -> [GroupStage] { let groupStages: [GroupStage] = self.tournamentStore.groupStages.filter { $0.tournament == self.id && $0.step == step } return groupStages.sorted(by: \.index) @@ -581,7 +586,8 @@ defer { } func pasteDataForImporting(_ exportFormat: ExportFormat = .rawText) -> String { - let selectedSortedTeams = selectedSortedTeams() + waitingListSortedTeams() + let _selectedSortedTeams = selectedSortedTeams() + let selectedSortedTeams = _selectedSortedTeams + waitingListSortedTeams(selectedSortedTeams: _selectedSortedTeams) switch exportFormat { case .rawText: return (selectedSortedTeams.compactMap { $0.pasteData(exportFormat) } + ["Liste d'attente"] + waitingListTeams(in: selectedSortedTeams, includingWalkOuts: true).compactMap { $0.pasteData(exportFormat) }).joined(separator: exportFormat.newLineSeparator(2)) @@ -878,13 +884,13 @@ defer { return rounds.sorted(by: \.index).reversed() } - func sortedTeams() -> [TeamRegistration] { - let teams = selectedSortedTeams() + func sortedTeams(selectedSortedTeams: [TeamRegistration]) -> [TeamRegistration] { + let teams = selectedSortedTeams return teams + waitingListTeams(in: teams, includingWalkOuts: true) } - func waitingListSortedTeams() -> [TeamRegistration] { - let teams = selectedSortedTeams() + func waitingListSortedTeams(selectedSortedTeams: [TeamRegistration]) -> [TeamRegistration] { + let teams = selectedSortedTeams return waitingListTeams(in: teams, includingWalkOuts: false) } @@ -1183,9 +1189,8 @@ defer { } } - func registrationIssues() -> Int { + func registrationIssues(selectedTeams: [TeamRegistration]) -> Int { let players : [PlayerRegistration] = unsortedPlayers() - let selectedTeams : [TeamRegistration] = selectedSortedTeams() let callDateIssue : [TeamRegistration] = selectedTeams.filter { $0.callDate != nil && isStartDateIsDifferentThanCallDate($0) } let duplicates : [PlayerRegistration] = duplicates(in: players) let problematicPlayers : [PlayerRegistration] = players.filter({ $0.sex == nil }) @@ -1852,6 +1857,7 @@ defer { team.wildCardGroupStage = true } + team.setWeight(from: [], inTournamentCategory: self.tournamentCategory) return team } @@ -1865,6 +1871,7 @@ defer { func addEmptyTeamRegistration(_ count: Int) { let teams = (0.. Date? { guard [.p500, .p1000, .p1500, .p2000].contains(tournamentLevel) else { return nil } - var daysOffset = type.daysOffset - if tournamentLevel == .p500 { - daysOffset += 7 - } + var daysOffset = type.daysOffset(level: tournamentLevel) if let date = Calendar.current.date(byAdding: .day, value: daysOffset, to: startDate) { let startOfDay = Calendar.current.startOfDay(for: date) return Calendar.current.date(byAdding: type.timeOffset, to: startOfDay) diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index ff9b1d8..dd7cbd2 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -1996,16 +1996,30 @@ enum TournamentDeadlineType: String, CaseIterable { case wildcardLicensePurchase = "Prise de licence des WC" case definitiveBroadcastList = "Publication définitive" - var daysOffset: Int { - switch self { - case .inscription: - return -13 - case .broadcastList: - return -12 - case .wildcardRequest: - return -9 - case .wildcardLicensePurchase, .definitiveBroadcastList: - return -8 + func daysOffset(level: TournamentLevel) -> Int { + if level == .p500 { + switch self { + case .inscription: + return -6 + case .broadcastList: + return -6 + case .wildcardRequest: + return -4 + case .wildcardLicensePurchase, .definitiveBroadcastList: + return -4 + } + } else { + switch self { + case .inscription: + return -13 + case .broadcastList: + return -12 + case .wildcardRequest: + return -9 + case .wildcardLicensePurchase, .definitiveBroadcastList: + return -8 + } + } } diff --git a/PadelClub/Views/Calling/SendToAllView.swift b/PadelClub/Views/Calling/SendToAllView.swift index d261f35..8a2adc2 100644 --- a/PadelClub/Views/Calling/SendToAllView.swift +++ b/PadelClub/Views/Calling/SendToAllView.swift @@ -223,13 +223,14 @@ struct SendToAllView: View { } func _teams() -> [TeamRegistration] { + let selectedSortedTeams = tournament.selectedSortedTeams() if onlyWaitingList { - return tournament.waitingListSortedTeams() + return tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams) } if _roundTeams().isEmpty && _groupStagesTeams().isEmpty { - return tournament.selectedSortedTeams() + (includeWaitingList ? tournament.waitingListSortedTeams() : []) + return tournament.selectedSortedTeams() + (includeWaitingList ? tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams) : []) } - return _roundTeams() + _groupStagesTeams() + (includeWaitingList ? tournament.waitingListSortedTeams() : []) + return _roundTeams() + _groupStagesTeams() + (includeWaitingList ? tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams) : []) } func _roundTeams() -> [TeamRegistration] { diff --git a/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift b/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift index 7d90518..9565658 100644 --- a/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift +++ b/PadelClub/Views/Navigation/Toolbox/MatchFormatStorageView.swift @@ -22,7 +22,7 @@ struct MatchFormatStorageView: View { var body: some View { Section { LabeledContent { - StepperView(title: "minutes", count: $estimatedDuration, step: 5) + StepperView(title: "minute", count: $estimatedDuration, step: 5) } label: { MatchFormatRowView(matchFormat: matchFormat, hideDuration: true) } diff --git a/PadelClub/Views/Planning/MatchFormatGuideView.swift b/PadelClub/Views/Planning/MatchFormatGuideView.swift new file mode 100644 index 0000000..4596a77 --- /dev/null +++ b/PadelClub/Views/Planning/MatchFormatGuideView.swift @@ -0,0 +1,72 @@ +// +// MatchFormatGuideView.swift +// PadelClub +// +// Created by razmig on 20/02/2025. +// + +import SwiftUI + +struct MatchFormatGuideView: View { + let matchCounts = Array(2...7) + let formats: [MatchFormat] = [ + .twoSets, .twoSetsDecisivePoint, + .twoSetsSuperTie, .twoSetsDecisivePointSuperTie, + .twoSetsOfFourGames, .twoSetsOfFourGamesDecisivePoint, + .nineGames, .nineGamesDecisivePoint, + .superTie + ] + + func getFormatDescription(for matchCount: Int) -> String { + var description = "" + + // Group formats by their behavior + let formatGroups = Dictionary(grouping: formats) { format in + format.maximumMatchPerDay(for: matchCount) + } + + // Sort by maximum matches allowed (descending) + let sortedMaxMatches = formatGroups.keys.sorted(by: >) + + for maxMatches in sortedMaxMatches { + if let formatsForMax = formatGroups[maxMatches] { + let formatStrings = formatsForMax.map { $0.format }.joined(separator: "/") + if maxMatches > 0 && maxMatches <= matchCount { + description += "Maximum \(maxMatches) matchs en format \(formatStrings)\n" + } else if maxMatches == 0 { + description += "Aucun match au format \(formatStrings)\n" + } + } + } + + if matchCount >= 7 { + description += "Format \(MatchFormat.superTie.format) principalement" + } + + return description.isEmpty ? "Aucun match possible" : description + } + + var body: some View { + List { + Section { + ForEach(matchCounts, id: \.self) { count in + VStack { + Text("\(count) matchs par jour") + .font(.headline) + Text(getFormatDescription(for: count)) + } + } + + // Special case for 7+ matches + VStack { + Text("7+ matchs par jour") + .font(.headline) + Text("Tournois P 25 uniquement (soirée/demi-journée/journée)") + } + } + } + .navigationTitle("Guide des Formats de Match") + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + } +} diff --git a/PadelClub/Views/Planning/PlanningSettingsView.swift b/PadelClub/Views/Planning/PlanningSettingsView.swift index 8a0d080..8a1d024 100644 --- a/PadelClub/Views/Planning/PlanningSettingsView.swift +++ b/PadelClub/Views/Planning/PlanningSettingsView.swift @@ -23,7 +23,8 @@ struct PlanningSettingsView: View { @State private var parallelType: Bool = false @State private var deletingDateMatchesDone: Bool = false @State private var deletingDone: Bool = false - + @State private var presentFormatHelperView: Bool = false + var tournamentStore: TournamentStore { return self.tournament.tournamentStore } @@ -145,6 +146,28 @@ struct PlanningSettingsView: View { _smartView() } + .navigationTitle("Réglages") + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button { + presentFormatHelperView = true + } label: { + Text("Aide-mémoire") + } + } + } + .sheet(isPresented: $presentFormatHelperView) { + NavigationStack { + MatchFormatGuideView() + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button("Retour", role: .cancel) { + presentFormatHelperView = false + } + } + } + } + } .headerProminence(.increased) .onAppear { do { diff --git a/PadelClub/Views/Team/Components/TeamWeightView.swift b/PadelClub/Views/Team/Components/TeamWeightView.swift index f19b6e6..0868ed3 100644 --- a/PadelClub/Views/Team/Components/TeamWeightView.swift +++ b/PadelClub/Views/Team/Components/TeamWeightView.swift @@ -12,16 +12,15 @@ struct TeamWeightView: View { let team: TeamRegistration var teamPosition: TeamPosition? = nil - var teamIndex: Int? { - team.tournamentObject()?.indexOf(team: team) - } + var teamIndex: Int? var displayWeight: Bool { - team.tournamentObject()?.hideWeight() == false + team.shouldDisplayRankAndWeight() && team.tournamentObject()?.hideWeight() == false } var body: some View { VStack(alignment: .trailing, spacing: 0) { + let displayWeight = self.displayWeight if (teamPosition == .one || teamPosition == nil) && displayWeight { Text(team.weight.formatted()) .monospacedDigit() diff --git a/PadelClub/Views/Team/EditingTeamView.swift b/PadelClub/Views/Team/EditingTeamView.swift index 76bbe32..8f06955 100644 --- a/PadelClub/Views/Team/EditingTeamView.swift +++ b/PadelClub/Views/Team/EditingTeamView.swift @@ -47,7 +47,8 @@ struct EditingTeamView: View { } private func _resetTeam() { - self.currentWaitingList = tournament.waitingListSortedTeams().filter({ $0.hasRegisteredOnline() }).first + let selectedSortedTeams = tournament.selectedSortedTeams() + self.currentWaitingList = tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams).filter({ $0.hasRegisteredOnline() }).first team.resetPositions() team.wildCardGroupStage = false team.walkOut = false diff --git a/PadelClub/Views/Team/TeamRowView.swift b/PadelClub/Views/Team/TeamRowView.swift index 966f903..4a1ba04 100644 --- a/PadelClub/Views/Team/TeamRowView.swift +++ b/PadelClub/Views/Team/TeamRowView.swift @@ -13,10 +13,11 @@ struct TeamRowView: View { var teamPosition: TeamPosition? = nil var displayCallDate: Bool = false var displayRestingTime: Bool = false + var teamIndex: Int? var body: some View { LabeledContent { - TeamWeightView(team: team, teamPosition: teamPosition) + TeamWeightView(team: team, teamPosition: teamPosition, teamIndex: teamIndex) } label: { VStack(alignment: .leading) { TeamHeadlineView(team: team) diff --git a/PadelClub/Views/Tournament/FileImportView.swift b/PadelClub/Views/Tournament/FileImportView.swift index 500d7dc..f72a8cc 100644 --- a/PadelClub/Views/Tournament/FileImportView.swift +++ b/PadelClub/Views/Tournament/FileImportView.swift @@ -312,7 +312,7 @@ struct FileImportView: View { } } else if didImport { let _filteredTeams = filteredTeams - let previousTeams = tournament.sortedTeams() + let previousTeams = tournament.sortedTeams(selectedSortedTeams: tournament.selectedSortedTeams()) if previousTeams.isEmpty == false { Section { diff --git a/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift b/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift index ebf4bde..2546787 100644 --- a/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift @@ -34,7 +34,7 @@ struct TournamentMatchFormatsSettingsView: View { Section { LabeledContent { - StepperView(title: "minutes", count: $tournament.additionalEstimationDuration, step: 5, minimum: -10) + StepperView(title: "minute", count: $tournament.additionalEstimationDuration, step: 5, minimum: -10) } label: { Text("Modifier les durées moyennes") } diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index e95fade..d4d875a 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -180,7 +180,7 @@ struct InscriptionManagerView: View { return _simpleHash(ids: ids1) != _simpleHash(ids: ids2) } - private func _setHash() { + private func _setHash(currentSelectedSortedTeams: [TeamRegistration]? = nil) { #if _DEBUG_TIME //DEBUGING TIME let start = Date() defer { @@ -188,18 +188,17 @@ struct InscriptionManagerView: View { print("func _setHash", duration.formatted(.units(allowed: [.seconds, .milliseconds]))) } #endif - let selectedSortedTeams = tournament.selectedSortedTeams() + let selectedSortedTeams = currentSelectedSortedTeams == nil ? tournament.selectedSortedTeams() : currentSelectedSortedTeams! if self.teamsHash == nil, selectedSortedTeams.isEmpty == false { self.teamsHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) } self.registrationIssues = nil DispatchQueue.main.async { - self.registrationIssues = tournament.registrationIssues() + self.registrationIssues = tournament.registrationIssues(selectedTeams: selectedSortedTeams) } } - private func _handleHashDiff() { - let selectedSortedTeams = tournament.selectedSortedTeams() + private func _handleHashDiff(selectedSortedTeams: [TeamRegistration]) { let newHash = _simpleHash(ids: selectedSortedTeams.map { $0.id }) if (self.teamsHash != nil && newHash != teamsHash!) || (self.teamsHash == nil && selectedSortedTeams.isEmpty == false) { self.teamsHash = newHash @@ -225,9 +224,10 @@ struct InscriptionManagerView: View { } var body: some View { - Group { - if tournament.unsortedTeams().isEmpty == false { - _teamRegisteredView() + let selectedSortedTeams = tournament.selectedSortedTeams() + return Group { + if tournament.unsortedTeamsCount() > 0 { + _teamRegisteredView(selectedSortedTeams: selectedSortedTeams) } else { List { @@ -263,10 +263,10 @@ struct InscriptionManagerView: View { await _refreshList() } .onAppear { - _setHash() + _setHash(currentSelectedSortedTeams: selectedSortedTeams) } .onDisappear { - _handleHashDiff() + _handleHashDiff(selectedSortedTeams: selectedSortedTeams) } .sheet(isPresented: $isLearningMore) { LearnMoreSheetView(tournament: tournament) @@ -490,47 +490,43 @@ struct InscriptionManagerView: View { tournament.unsortedPlayers() } - var sortedTeams: [TeamRegistration] { + func sortedTeams(selectedSortedTeams: [TeamRegistration]) -> [TeamRegistration] { if filterMode == .waiting { - return tournament.waitingListSortedTeams() + return tournament.waitingListSortedTeams(selectedSortedTeams: selectedSortedTeams) } else { - return tournament.sortedTeams() + return tournament.sortedTeams(selectedSortedTeams: selectedSortedTeams) } } - var filteredTeams: [TeamRegistration] { - - var teams = sortedTeams - switch filterMode { - case .wildcardBracket: - teams = teams.filter({ $0.wildCardBracket }) - case .wildcardGroupStage: - teams = teams.filter({ $0.wildCardGroupStage }) - case .walkOut: - teams = teams.filter({ $0.walkOut }) - case .bracket: - teams = teams.filter({ $0.inRound() && $0.inGroupStage() == false }) - case .groupStage: - teams = teams.filter({ $0.inGroupStage() }) - case .notImported: - teams = teams.filter({ $0.isImported() == false }) - case .registeredLocally: - teams = teams.filter({ $0.hasRegisteredOnline() == false }) - case .registeredOnline: - teams = teams.filter({ $0.hasRegisteredOnline() == true }) - default: - break - } - - if sortingMode == .registrationDate { - teams = teams.sorted(by: \.computedRegistrationDate) + func filteredTeams(sortedTeams: [TeamRegistration]) -> [TeamRegistration] { + let filtered = sortedTeams.lazy.filter { team in + switch filterMode { + case .wildcardBracket: + return team.wildCardBracket + case .wildcardGroupStage: + return team.wildCardGroupStage + case .walkOut: + return team.walkOut + case .bracket: + return team.inRound() && !team.inGroupStage() + case .groupStage: + return team.inGroupStage() + case .notImported: + return !team.isImported() + case .registeredLocally: + return !team.hasRegisteredOnline() + case .registeredOnline: + return team.hasRegisteredOnline() + default: + return true + } } - if byDecreasingOrdering { - return teams.reversed() - } else { - return teams - } + let sorted = sortingMode == .registrationDate + ? filtered.sorted(by: { $0.computedRegistrationDate < $1.computedRegistrationDate }) + : Array(filtered) + + return byDecreasingOrdering ? sorted.reversed() : sorted } // private func _fixModel() { @@ -572,12 +568,10 @@ struct InscriptionManagerView: View { } } - private func _teamRegisteredView() -> some View { + private func _teamRegisteredView(selectedSortedTeams: [TeamRegistration]) -> some View { List { - let selectedSortedTeams = tournament.selectedSortedTeams() - if presentSearch == false { - _informationView() + _informationView(for: selectedSortedTeams) if tournament.isAnimation() == false { _rankHandlerView() @@ -585,7 +579,8 @@ struct InscriptionManagerView: View { } } - let teams = searchField.isEmpty ? filteredTeams : filteredTeams.filter({ $0.contains(searchField.canonicalVersion) }) + let sortedTeams = sortedTeams(selectedSortedTeams: selectedSortedTeams) + let teams = searchField.isEmpty ? filteredTeams(sortedTeams: sortedTeams) : filteredTeams(sortedTeams: sortedTeams).filter({ $0.contains(searchField.canonicalVersion) }) if teams.isEmpty && searchField.isEmpty == false { ContentUnavailableView { @@ -622,7 +617,7 @@ struct InscriptionManagerView: View { EditingTeamView(team: team) .environment(tournament) } label: { - TeamRowView(team: team) + TeamRowView(team: team, teamIndex: teamIndex) } .swipeActions(edge: .trailing, allowsFullSwipe: true) { if tournament.enableOnlineRegistration == false { @@ -735,18 +730,18 @@ struct InscriptionManagerView: View { } } - private func _teamCountForFilterMode(filterMode: FilterMode) -> String { + private func _teamCountForFilterMode(filterMode: FilterMode, in teams: [TeamRegistration]) -> String { switch filterMode { case .wildcardBracket: - return tournament.selectedSortedTeams().filter({ $0.wildCardBracket }).count.formatted() + return teams.filter({ $0.wildCardBracket }).count.formatted() case .wildcardGroupStage: - return tournament.selectedSortedTeams().filter({ $0.wildCardGroupStage }).count.formatted() + return teams.filter({ $0.wildCardGroupStage }).count.formatted() case .all: return unsortedTeamsWithoutWO.count.formatted() case .bracket: - return tournament.selectedSortedTeams().filter({ $0.inRound() && $0.inGroupStage() == false }).count.formatted() + return teams.filter({ $0.inRound() && $0.inGroupStage() == false }).count.formatted() case .groupStage: - return tournament.selectedSortedTeams().filter({ $0.inGroupStage() }).count.formatted() + return teams.filter({ $0.inGroupStage() }).count.formatted() case .walkOut: let wo = walkoutTeams.count.formatted() return wo @@ -754,20 +749,20 @@ struct InscriptionManagerView: View { let waiting: Int = max(0, unsortedTeamsWithoutWO.count - tournament.teamCount) return waiting.formatted() case .notImported: - let notImported: Int = max(0, sortedTeams.filter({ $0.isImported() == false }).count) + let notImported: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.isImported() == false }).count) return notImported.formatted() case .registeredLocally: - let registeredLocally: Int = max(0, sortedTeams.filter({ $0.hasRegisteredOnline() == false }).count) + let registeredLocally: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.hasRegisteredOnline() == false }).count) return registeredLocally.formatted() case .registeredOnline: - let registeredOnline: Int = max(0, sortedTeams.filter({ $0.hasRegisteredOnline() }).count) + let registeredOnline: Int = max(0, sortedTeams(selectedSortedTeams: teams).filter({ $0.hasRegisteredOnline() }).count) return registeredOnline.formatted() } } @ViewBuilder - private func _informationView() -> some View { + private func _informationView(for teams: [TeamRegistration]) -> some View { Section { HStack { // VStack(alignment: .leading, spacing: 0) { @@ -781,7 +776,7 @@ struct InscriptionManagerView: View { // } // ForEach([FilterMode.all, FilterMode.waiting, FilterMode.walkOut]) { filterMode in - _filterModeView(filterMode: filterMode) + _filterModeView(filterMode: filterMode, in: teams) } Button { @@ -809,7 +804,7 @@ struct InscriptionManagerView: View { .listRowSeparator(.hidden) HStack { ForEach([FilterMode.groupStage, FilterMode.bracket, FilterMode.wildcardGroupStage, FilterMode.wildcardBracket]) { filterMode in - _filterModeView(filterMode: filterMode) + _filterModeView(filterMode: filterMode, in: teams) } } .padding(.bottom, -4) @@ -883,7 +878,7 @@ struct InscriptionManagerView: View { } } - private func _filterModeView(filterMode: FilterMode) -> some View { + private func _filterModeView(filterMode: FilterMode, in teams: [TeamRegistration]) -> some View { Button { if self.filterMode == filterMode { @@ -894,7 +889,7 @@ struct InscriptionManagerView: View { } label: { VStack(alignment: .center, spacing: -2) { Text(filterMode.localizedLabel(.short)).font(.caption).padding(.horizontal, -8) - Text(_teamCountForFilterMode(filterMode: filterMode)).font(.largeTitle) + Text(_teamCountForFilterMode(filterMode: filterMode, in: teams)).font(.largeTitle) } .frame(maxWidth: .infinity) .contentShape(Rectangle())