From 44f4b3e56670b44a0b543de97bbad6cfdb3f62b9 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Thu, 2 May 2024 12:43:46 +0200 Subject: [PATCH 1/6] fix launcscreen warning --- PadelClub.xcodeproj/project.pbxproj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index c1d13cd..c1f13cc 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -131,6 +131,7 @@ FF3B60A32BC49BBC008C2E66 /* MatchScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3B60A22BC49BBC008C2E66 /* MatchScheduler.swift */; }; FF3F74F62B919E45004CFE0E /* UmpireView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3F74F52B919E45004CFE0E /* UmpireView.swift */; }; FF3F74FF2B91A2D4004CFE0E /* AgendaDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF3F74FE2B91A2D4004CFE0E /* AgendaDestination.swift */; }; + FF44421C2BE39FA2008BBF0B /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FFD784002B91BF79000F62A6 /* Launch Screen.storyboard */; }; FF4AB6B52B9248200002987F /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4AB6B42B9248200002987F /* NetworkManager.swift */; }; FF4AB6BB2B9256D50002987F /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4AB6BA2B9256D50002987F /* SearchViewModel.swift */; }; FF4AB6BD2B9256E10002987F /* SelectablePlayerListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4AB6BC2B9256E10002987F /* SelectablePlayerListView.swift */; }; @@ -1369,6 +1370,7 @@ buildActionMask = 2147483647; files = ( C425D4082B6D249E002A7B48 /* Preview Assets.xcassets in Resources */, + FF44421C2BE39FA2008BBF0B /* Launch Screen.storyboard in Resources */, FF0EC54E2BB195E20056B6D1 /* CLASSEMENT-PADEL-MESSIEURS-2-02-2023.csv in Resources */, FF0EC54F2BB195E20056B6D1 /* CLASSEMENT-PADEL-MESSIEURS-08-2022.csv in Resources */, FF0EC5502BB195E20056B6D1 /* CLASSEMENT-PADEL-DAMES-12-2022.csv in Resources */, @@ -1808,7 +1810,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1817,6 +1819,7 @@ INFOPLIST_FILE = PadelClub/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Padel Club"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports"; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Padel Club a besoin de votre position pour rechercher les clubs autour de vous."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -1842,7 +1845,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1851,6 +1854,7 @@ INFOPLIST_FILE = PadelClub/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Padel Club"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports"; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "Padel Club a besoin de votre position pour rechercher les clubs autour de vous."; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; From 80dbc664785f27fdea3871218503ca08e78f8464 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Thu, 2 May 2024 16:38:01 +0200 Subject: [PATCH 2/6] update some DB stuff --- PadelClub/Data/AppSettings.swift | 1 + PadelClub/Data/Club.swift | 6 ++- PadelClub/Data/Event.swift | 6 ++- PadelClub/Data/PlayerRegistration.swift | 35 +++++++++++------ PadelClub/Data/TeamRegistration.swift | 39 +++++-------------- PadelClub/Data/Tournament.swift | 18 ++++----- PadelClub/Data/User.swift | 18 +++++++++ PadelClub/Info.plist | 2 + PadelClub/Utils/PadelRule.swift | 11 ++++++ .../Views/Cashier/CashierDetailView.swift | 4 +- .../Views/Cashier/CashierSettingsView.swift | 4 +- .../Player/Components/PlayerPayView.swift | 10 ++--- .../Components/PlayerSexPickerView.swift | 2 +- PadelClub/Views/Player/PlayerDetailView.swift | 4 +- .../Components/UpdateSourceRankDateView.swift | 2 +- .../Screen/InscriptionManagerView.swift | 2 +- 16 files changed, 96 insertions(+), 68 deletions(-) diff --git a/PadelClub/Data/AppSettings.swift b/PadelClub/Data/AppSettings.swift index d98497a..e2a6426 100644 --- a/PadelClub/Data/AppSettings.swift +++ b/PadelClub/Data/AppSettings.swift @@ -15,6 +15,7 @@ class AppSettings: MicroStorable { static var fileName: String { "appsettings.json" } var lastDataSource: String? = nil + var callMessageBody : String? = nil var callMessageSignature: String? = nil var callDisplayFormat: Bool = false diff --git a/PadelClub/Data/Club.swift b/PadelClub/Data/Club.swift index 2d23616..98fb664 100644 --- a/PadelClub/Data/Club.swift +++ b/PadelClub/Data/Club.swift @@ -23,10 +23,12 @@ class Club : ModelObject, Storable, Hashable { } var id: String = Store.randomId() + var creator: String? var name: String var acronym: String var phone: String? var code: String? + //var federalClubData: Data? var address: String? var city: String? var zipCode: String? @@ -34,7 +36,8 @@ class Club : ModelObject, Storable, Hashable { var longitude: Double? //var courtCount: Int? - internal init(name: String, acronym: String? = nil, phone: String? = nil, code: String? = nil, address: String? = nil, city: String? = nil, zipCode: String? = nil, latitude: Double? = nil, longitude: Double? = nil) { + internal init(creator: String? = nil, name: String, acronym: String? = nil, phone: String? = nil, code: String? = nil, address: String? = nil, city: String? = nil, zipCode: String? = nil, latitude: Double? = nil, longitude: Double? = nil) { + self.creator = creator self.name = name self.acronym = acronym ?? name.acronym() self.phone = phone @@ -69,6 +72,7 @@ class Club : ModelObject, Storable, Hashable { enum CodingKeys: String, CodingKey { case _id = "id" + case _creator = "creator" case _name = "name" case _acronym = "acronym" case _phone = "phone" diff --git a/PadelClub/Data/Event.swift b/PadelClub/Data/Event.swift index 3aba007..a33e05f 100644 --- a/PadelClub/Data/Event.swift +++ b/PadelClub/Data/Event.swift @@ -14,9 +14,11 @@ class Event: ModelObject, Storable { static func resourceName() -> String { return "events" } var id: String = Store.randomId() + var creator: String? var club: String? var creationDate: Date = Date() var name: String? + //var federalTournamentData: Data? //var courtCount: Int? var tenupId: String? // var groupStageFormat: Int? @@ -24,7 +26,8 @@ class Event: ModelObject, Storable { // var loserRoundFormat: Int? //var timeslots ? - internal init(club: String? = nil, name: String? = nil, tenupId: String? = nil) { + internal init(creator: String? = nil, club: String? = nil, name: String? = nil, tenupId: String? = nil) { + self.creator = creator self.club = club self.name = name // self.courtCount = courtCount @@ -61,6 +64,7 @@ class Event: ModelObject, Storable { extension Event { enum CodingKeys: String, CodingKey { case _id = "id" + case _creator = "creator" case _club = "club" case _creationDate = "creationDate" case _name = "name" diff --git a/PadelClub/Data/PlayerRegistration.swift b/PadelClub/Data/PlayerRegistration.swift index a3db02b..428bd6c 100644 --- a/PadelClub/Data/PlayerRegistration.swift +++ b/PadelClub/Data/PlayerRegistration.swift @@ -18,9 +18,8 @@ class PlayerRegistration: ModelObject, Storable { var lastName: String var licenceId: String? var rank: Int? - var registrationType: PaymentType? - var registrationDate: Date? - var sex: Int + var paymentType: PlayerPaymentType? + var sex: Int //todo var tournamentPlayed: Int? var points: Double? @@ -37,14 +36,13 @@ class PlayerRegistration: ModelObject, Storable { var hasArrived: Bool = false - internal init(teamRegistration: String? = nil, firstName: String, lastName: String, licenceId: String? = nil, rank: Int? = nil, registrationType: PaymentType? = nil, registrationDate: Date? = nil, sex: Int, source: PlayerDataSource? = nil) { + internal init(teamRegistration: String? = nil, firstName: String, lastName: String, licenceId: String? = nil, rank: Int? = nil, paymentType: PlayerPaymentType? = nil, sex: Int, source: PlayerDataSource? = nil) { self.teamRegistration = teamRegistration self.firstName = firstName self.lastName = lastName self.licenceId = licenceId self.rank = rank - self.registrationType = registrationType - self.registrationDate = registrationDate + self.paymentType = paymentType self.sex = sex self.source = source } @@ -135,7 +133,7 @@ class PlayerRegistration: ModelObject, Storable { } func hasPaid() -> Bool { - registrationType != nil + paymentType != nil } func playerLabel(_ displayStyle: DisplayStyle = .wide) -> String { @@ -265,8 +263,7 @@ class PlayerRegistration: ModelObject, Storable { case _lastName = "lastName" case _licenceId = "licenceId" case _rank = "rank" - case _registrationType = "registrationType" - case _registrationDate = "registrationDate" + case _paymentType = "paymentType" case _sex = "sex" case _tournamentPlayed = "tournamentPlayed" case _points = "points" @@ -283,11 +280,25 @@ class PlayerRegistration: ModelObject, Storable { } enum PlayerDataSource: Int, Codable { - case frenchFederation - case beachPadel + case frenchFederation = 0 + case beachPadel = 1 } - enum PaymentType: Int, CaseIterable, Identifiable, Codable { + enum PlayerSexType: Int, CaseIterable, Identifiable, Codable { + init?(rawValue: Int?) { + guard let value = rawValue else { return nil } + self.init(rawValue: value) + } + + var id: Self { + self + } + + case female = 0 + case male = 1 + } + + enum PlayerPaymentType: Int, CaseIterable, Identifiable, Codable { init?(rawValue: Int?) { guard let value = rawValue else { return nil } self.init(rawValue: value) diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 1b8b5d2..8d2f3a2 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -28,13 +28,12 @@ class TeamRegistration: ModelObject, Storable { var walkOut: Bool = false var wildCardBracket: Bool = false var wildCardGroupStage: Bool = false - var category: TournamentCategory? var weight: Int = 0 var lockWeight: Int? var confirmationDate: Date? var qualified: Bool = false - internal init(tournament: String, groupStage: String? = nil, registrationDate: Date? = nil, callDate: Date? = nil, bracketPosition: Int? = nil, groupStagePosition: Int? = nil, comment: String? = nil, source: String? = nil, sourceValue: String? = nil, logo: String? = nil, name: String? = nil, category: TournamentCategory? = nil) { + internal init(tournament: String, groupStage: String? = nil, registrationDate: Date? = nil, callDate: Date? = nil, bracketPosition: Int? = nil, groupStagePosition: Int? = nil, comment: String? = nil, source: String? = nil, sourceValue: String? = nil, logo: String? = nil, name: String? = nil) { self.tournament = tournament self.groupStage = groupStage self.registrationDate = registrationDate @@ -46,7 +45,6 @@ class TeamRegistration: ModelObject, Storable { self.sourceValue = sourceValue self.logo = logo self.name = name - self.category = category } func isSeedable() -> Bool { @@ -101,12 +99,7 @@ class TeamRegistration: ModelObject, Storable { } var tournamentCategory: TournamentCategory { - get { - category ?? .men - } - set { - category = newValue - } + tournamentObject()?.tournamentCategory ?? .men } @objc @@ -121,8 +114,8 @@ class TeamRegistration: ModelObject, Storable { }) } - func updateWeight() { - setWeight(from: self.players()) + func updateWeight(inTournamentCategory tournamentCategory: TournamentCategory) { + setWeight(from: self.players(), inTournamentCategory: tournamentCategory) } func teamLabel(_ displayStyle: DisplayStyle = .wide) -> String { @@ -201,9 +194,9 @@ class TeamRegistration: ModelObject, Storable { } - func updatePlayers(_ players: Set) { + func updatePlayers(_ players: Set, inTournamentCategory tournamentCategory: TournamentCategory) { try? DataStore.shared.playerRegistrations.delete(contentOfs: unsortedPlayers()) - setWeight(from: Array(players)) + setWeight(from: Array(players), inTournamentCategory: tournamentCategory) players.forEach { player in player.teamRegistration = id @@ -273,31 +266,20 @@ class TeamRegistration: ModelObject, Storable { Store.main.filter { $0.teamRegistration == self.id } } - func setWeight(from players: [PlayerRegistration]) { + func setWeight(from players: [PlayerRegistration], inTournamentCategory tournamentCategory: TournamentCategory) { let significantPlayerCount = significantPlayerCount() - weight = (players.prefix(significantPlayerCount).map { $0.weight } + missingPlayerType().map { unrankValue(for: $0 == 1 ? true : false ) }).prefix(significantPlayerCount).reduce(0,+) + weight = (players.prefix(significantPlayerCount).map { $0.weight } + missingPlayerType(inTournamentCategory: tournamentCategory).map { unrankValue(for: $0 == 1 ? true : false ) }).prefix(significantPlayerCount).reduce(0,+) } func significantPlayerCount() -> Int { tournamentObject()?.significantPlayerCount() ?? 2 } - func mandatoryPlayerType() -> [Int] { - switch tournamentCategory { - case .mix: - return [0, 1] - case .women: - return [0, 0] - case .men: - return [1, 1] - } - } - - func missingPlayerType() -> [Int] { + func missingPlayerType(inTournamentCategory tournamentCategory: TournamentCategory) -> [Int] { let players = unsortedPlayers() if players.count >= 2 { return [] } let s = players.map { $0.sex } - var missing = mandatoryPlayerType() + var missing = tournamentCategory.mandatoryPlayerType() s.forEach { i in if let index = missing.firstIndex(of: i) { missing.remove(at: index) @@ -351,7 +333,6 @@ class TeamRegistration: ModelObject, Storable { case _name = "name" case _wildCardBracket = "wildCardBracket" case _wildCardGroupStage = "wildCardGroupStage" - case _category = "category" case _weight = "weight" case _walkOut = "walkOut" case _lockWeight = "lockWeight" diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index fdcffe6..918a6c1 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -14,7 +14,6 @@ class Tournament : ModelObject, Storable { var id: String = Store.randomId() var event: String? - var creator: String? var name: String? var startDate: Date var endDate: Date? @@ -49,9 +48,8 @@ class Tournament : ModelObject, Storable { @ObservationIgnored var navigationPath: [Screen] = [] - internal init(event: String? = nil, creator: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = true, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, seedCount: Int = 8, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil) { + internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = true, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, seedCount: Int = 8, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil) { self.event = event - self.creator = creator self.name = name self.startDate = startDate self.endDate = endDate @@ -539,7 +537,7 @@ class Tournament : ModelObject, Storable { var teamsToImport = [TeamRegistration]() teams.forEach { team in if let previousTeam = team.previousTeam { - previousTeam.updatePlayers(team.players) + previousTeam.updatePlayers(team.players, inTournamentCategory: team.tournamentCategory) teamsToImport.append(previousTeam) } else { let newTeam = addTeam(team.players, registrationDate: team.registrationDate) @@ -671,7 +669,7 @@ class Tournament : ModelObject, Storable { teams.forEach { team in let players = team.unsortedPlayers() players.forEach { $0.setWeight(in: self) } - team.setWeight(from: players) + team.setWeight(from: players, inTournamentCategory: tournamentCategory) try? DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: players) } try? DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teams) @@ -985,8 +983,7 @@ class Tournament : ModelObject, Storable { func addTeam(_ players: Set, registrationDate: Date? = nil) -> TeamRegistration { let team = TeamRegistration(tournament: id, registrationDate: registrationDate ?? Date()) - team.tournamentCategory = tournamentCategory - team.setWeight(from: Array(players)) + team.setWeight(from: Array(players), inTournamentCategory: tournamentCategory) players.forEach { player in player.teamRegistration = team.id } @@ -1271,7 +1268,6 @@ extension Tournament { enum CodingKeys: String, CodingKey { case _id = "id" case _event = "event" - case _creator = "creator" case _name = "name" case _startDate = "startDate" case _endDate = "endDate" @@ -1364,12 +1360,12 @@ extension Tournament { let tournamentLevel = TournamentLevel.mostUsed(inTournaments: tournaments) let tournamentCategory = TournamentCategory.mostUsed(inTournaments: tournaments) let federalTournamentAge = FederalTournamentAge.mostUsed(inTournaments: tournaments) - - return Tournament(creator: DataStore.shared.user?.id, groupStageSortMode: .snake, rankSourceDate: rankSourceDate, teamSorting: tournamentLevel.defaultTeamSortingType, federalCategory: tournamentCategory, federalLevelCategory: tournamentLevel, federalAgeCategory: federalTournamentAge) +//creator: DataStore.shared.user?.id + return Tournament(groupStageSortMode: .snake, rankSourceDate: rankSourceDate, teamSorting: tournamentLevel.defaultTeamSortingType, federalCategory: tournamentCategory, federalLevelCategory: tournamentLevel, federalAgeCategory: federalTournamentAge) } static func fake() -> Tournament { - return Tournament(event: "Roland Garros", creator: "", name: "Magic P100", startDate: Date(), endDate: Date(), creationDate: Date(), isPrivate: false, groupStageFormat: .nineGames, roundFormat: nil, loserRoundFormat: nil, groupStageSortMode: .snake, groupStageCount: 4, rankSourceDate: nil, dayDuration: 2, teamCount: 24, teamSorting: .rank, federalCategory: .men, federalLevelCategory: .p100, federalAgeCategory: .a45, groupStageCourtCount: nil, seedCount: 8, closedRegistrationDate: nil, groupStageAdditionalQualified: 0, courtCount: 4, prioritizeClubMembers: false, qualifiedPerGroupStage: 2, teamsPerGroupStage: 4, entryFee: nil) + return Tournament(event: "Roland Garros", name: "Magic P100", startDate: Date(), endDate: Date(), creationDate: Date(), isPrivate: false, groupStageFormat: .nineGames, roundFormat: nil, loserRoundFormat: nil, groupStageSortMode: .snake, groupStageCount: 4, rankSourceDate: nil, dayDuration: 2, teamCount: 24, teamSorting: .rank, federalCategory: .men, federalLevelCategory: .p100, federalAgeCategory: .a45, groupStageCourtCount: nil, seedCount: 8, closedRegistrationDate: nil, groupStageAdditionalQualified: 0, courtCount: 4, prioritizeClubMembers: false, qualifiedPerGroupStage: 2, teamsPerGroupStage: 4, entryFee: nil) } } diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index 1626594..96e2e49 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -27,6 +27,15 @@ class User: UserBase { var lastName: String var phone: String? var country: String? + var callMessageBody : String? = nil + var callMessageSignature: String? = nil + var callDisplayFormat: Bool = false + var callDisplayEntryFee: Bool = false + var callUseFullCustomMessage: Bool = false + var matchFormatsDefaultDuration: [MatchFormat: Int]? = nil + var bracketMatchFormatPreference: MatchFormat? + var groupStageMatchFormatPreference: MatchFormat? + var loserBracketMatchFormatPreference: MatchFormat? init(username: String, email: String, firstName: String, lastName: String, phone: String?, country: String?) { self.username = username @@ -64,6 +73,15 @@ class User: UserBase { case _lastName = "lastName" case _phone = "phone" case _country = "country" + case _callMessageBody = "callMessageBody" + case _callMessageSignature = "callMessageSignature" + case _callDisplayFormat = "callDisplayFormat" + case _callDisplayEntryFee = "callDisplayEntryFee" + case _callUseFullCustomMessage = "callUseFullCustomMessage" + case _matchFormatsDefaultDuration = "matchFormatsDefaultDuration" + case _bracketMatchFormatPreference = "bracketMatchFormatPreference" + case _groupStageMatchFormatPreference = "groupStageMatchFormatPreference" + case _loserBracketMatchFormatPreference = "loserBracketMatchFormatPreference" } } diff --git a/PadelClub/Info.plist b/PadelClub/Info.plist index 4562fb0..f3a644a 100644 --- a/PadelClub/Info.plist +++ b/PadelClub/Info.plist @@ -18,5 +18,7 @@ + ITSAppUsesNonExemptEncryption + diff --git a/PadelClub/Utils/PadelRule.swift b/PadelClub/Utils/PadelRule.swift index 11118db..fa1bad3 100644 --- a/PadelClub/Utils/PadelRule.swift +++ b/PadelClub/Utils/PadelRule.swift @@ -638,6 +638,17 @@ enum TournamentCategory: Int, Hashable, Codable, CaseIterable, Identifiable { self.init(rawValue: value) } + func mandatoryPlayerType() -> [Int] { + switch self { + case .mix: + return [0, 1] + case .women: + return [0, 0] + case .men: + return [1, 1] + } + } + var localizedPlayerLabel: String { switch self { case .women: diff --git a/PadelClub/Views/Cashier/CashierDetailView.swift b/PadelClub/Views/Cashier/CashierDetailView.swift index 7070584..38dd496 100644 --- a/PadelClub/Views/Cashier/CashierDetailView.swift +++ b/PadelClub/Views/Cashier/CashierDetailView.swift @@ -42,8 +42,8 @@ struct CashierDetailView: View { private func _tournamentCashierDetailView(_ tournament: Tournament) -> some View { DisclosureGroup { - ForEach(PlayerRegistration.PaymentType.allCases) { type in - let count = tournament.selectedPlayers().filter({ $0.registrationType == type }).count + ForEach(PlayerRegistration.PlayerPaymentType.allCases) { type in + let count = tournament.selectedPlayers().filter({ $0.paymentType == type }).count LabeledContent { if let entryFee = tournament.entryFee { let sum = Double(count) * entryFee diff --git a/PadelClub/Views/Cashier/CashierSettingsView.swift b/PadelClub/Views/Cashier/CashierSettingsView.swift index 08d8331..8b1871d 100644 --- a/PadelClub/Views/Cashier/CashierSettingsView.swift +++ b/PadelClub/Views/Cashier/CashierSettingsView.swift @@ -26,7 +26,7 @@ struct CashierSettingsView: View { let players = tournaments.flatMap({ $0.selectedPlayers() }) players.forEach { player in if player.hasPaid() == false { - player.registrationType = .gift + player.paymentType = .gift } } try? dataStore.playerRegistrations.addOrUpdate(contentOfs: players) @@ -39,7 +39,7 @@ struct CashierSettingsView: View { RowButtonView("Personne n'a réglé", role: .destructive) { let players = tournaments.flatMap({ $0.selectedPlayers() }) players.forEach { player in - player.registrationType = nil + player.paymentType = nil } try? dataStore.playerRegistrations.addOrUpdate(contentOfs: players) } diff --git a/PadelClub/Views/Player/Components/PlayerPayView.swift b/PadelClub/Views/Player/Components/PlayerPayView.swift index 721dcef..649bdd7 100644 --- a/PadelClub/Views/Player/Components/PlayerPayView.swift +++ b/PadelClub/Views/Player/Components/PlayerPayView.swift @@ -12,16 +12,16 @@ struct PlayerPayView: View { @Bindable var player: PlayerRegistration var body: some View { - Picker(selection: $player.registrationType) { - Text("Non réglé").tag(nil as PlayerRegistration.PaymentType?) - ForEach(PlayerRegistration.PaymentType.allCases) { type in - Text(type.localizedLabel()).tag(type as PlayerRegistration.PaymentType?) + Picker(selection: $player.paymentType) { + Text("Non réglé").tag(nil as PlayerRegistration.PlayerPaymentType?) + ForEach(PlayerRegistration.PlayerPaymentType.allCases) { type in + Text(type.localizedLabel()).tag(type as PlayerRegistration.PlayerPaymentType?) } } label: { } .pickerStyle(.menu) .fixedSize() - .onChange(of: player.registrationType) { + .onChange(of: player.paymentType) { _save() } } diff --git a/PadelClub/Views/Player/Components/PlayerSexPickerView.swift b/PadelClub/Views/Player/Components/PlayerSexPickerView.swift index 9964bd2..e3b3d38 100644 --- a/PadelClub/Views/Player/Components/PlayerSexPickerView.swift +++ b/PadelClub/Views/Player/Components/PlayerSexPickerView.swift @@ -35,7 +35,7 @@ struct PlayerSexPickerView: View { player.setWeight(in: tournament) try dataStore.playerRegistrations.addOrUpdate(instance: player) if let team = player.team() { - team.updateWeight() + team.updateWeight(inTournamentCategory: tournament.tournamentCategory) try dataStore.teamRegistrations.addOrUpdate(instance: team) } diff --git a/PadelClub/Views/Player/PlayerDetailView.swift b/PadelClub/Views/Player/PlayerDetailView.swift index 6b0624a..e6289a0 100644 --- a/PadelClub/Views/Player/PlayerDetailView.swift +++ b/PadelClub/Views/Player/PlayerDetailView.swift @@ -80,12 +80,12 @@ struct PlayerDetailView: View { _save() } .onChange(of: player.weight) { - player.team()?.updateWeight() + player.team()?.updateWeight(inTournamentCategory: tournament.tournamentCategory) _save() } .onChange(of: player.rank) { player.setWeight(in: tournament) - player.team()?.updateWeight() + player.team()?.updateWeight(inTournamentCategory: tournament.tournamentCategory) _save() } .headerProminence(.increased) diff --git a/PadelClub/Views/Tournament/Screen/Components/UpdateSourceRankDateView.swift b/PadelClub/Views/Tournament/Screen/Components/UpdateSourceRankDateView.swift index d7f58c6..6024b6e 100644 --- a/PadelClub/Views/Tournament/Screen/Components/UpdateSourceRankDateView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/UpdateSourceRankDateView.swift @@ -46,7 +46,7 @@ struct UpdateSourceRankDateView: View { try dataStore.playerRegistrations.addOrUpdate(contentOfs: tournament.unsortedPlayers()) tournament.unsortedTeams().forEach { team in - team.setWeight(from: team.players()) + team.setWeight(from: team.players(), inTournamentCategory: tournament.tournamentCategory) if forceRefreshLockWeight { team.lockWeight = team.weight } diff --git a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift index f145131..d0d202e 100644 --- a/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift +++ b/PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift @@ -555,7 +555,7 @@ struct InscriptionManagerView: View { private func _updateTeam() { guard let editedTeam else { return } let players = _currentSelection() - editedTeam.updatePlayers(players) + editedTeam.updatePlayers(players, inTournamentCategory: tournament.tournamentCategory) try? dataStore.teamRegistrations.addOrUpdate(instance: editedTeam) try? dataStore.playerRegistrations.addOrUpdate(contentOfs: players) createdPlayers.removeAll() From 2f65fc9ae16e518f1a9925d85faa5dc42ef3aa86 Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Thu, 2 May 2024 19:06:38 +0200 Subject: [PATCH 3/6] fix DB Stuff --- PadelClub/Data/MockData.swift | 2 +- PadelClub/Data/PlayerRegistration.swift | 18 +++++++++--------- PadelClub/Data/TeamRegistration.swift | 4 ++-- PadelClub/Data/Tournament.swift | 11 ++++------- PadelClub/Data/User.swift | 18 ------------------ PadelClub/ViewModel/AgendaDestination.swift | 2 ++ .../Player/Components/PlayerPopoverView.swift | 2 +- .../Components/PlayerSexPickerView.swift | 4 ++-- .../Components/InscriptionInfoView.swift | 2 +- 9 files changed, 22 insertions(+), 41 deletions(-) diff --git a/PadelClub/Data/MockData.swift b/PadelClub/Data/MockData.swift index d2bd29a..30adfa2 100644 --- a/PadelClub/Data/MockData.swift +++ b/PadelClub/Data/MockData.swift @@ -61,6 +61,6 @@ extension TeamRegistration { extension PlayerRegistration { static func mock() -> PlayerRegistration { - PlayerRegistration(firstName: "Raz", lastName: "Shark", sex: 1) + PlayerRegistration(firstName: "Raz", lastName: "Shark", sex: .male) } } diff --git a/PadelClub/Data/PlayerRegistration.swift b/PadelClub/Data/PlayerRegistration.swift index 428bd6c..74d7196 100644 --- a/PadelClub/Data/PlayerRegistration.swift +++ b/PadelClub/Data/PlayerRegistration.swift @@ -19,7 +19,7 @@ class PlayerRegistration: ModelObject, Storable { var licenceId: String? var rank: Int? var paymentType: PlayerPaymentType? - var sex: Int //todo + var sex: PlayerSexType? var tournamentPlayed: Int? var points: Double? @@ -36,7 +36,7 @@ class PlayerRegistration: ModelObject, Storable { var hasArrived: Bool = false - internal init(teamRegistration: String? = nil, firstName: String, lastName: String, licenceId: String? = nil, rank: Int? = nil, paymentType: PlayerPaymentType? = nil, sex: Int, source: PlayerDataSource? = nil) { + internal init(teamRegistration: String? = nil, firstName: String, lastName: String, licenceId: String? = nil, rank: Int? = nil, paymentType: PlayerPaymentType? = nil, sex: PlayerSexType?, source: PlayerDataSource? = nil) { self.teamRegistration = teamRegistration self.firstName = firstName self.lastName = lastName @@ -53,7 +53,7 @@ class PlayerRegistration: ModelObject, Storable { self.lastName = importedPlayer.lastName ?? "" self.licenceId = importedPlayer.license ?? nil self.rank = Int(importedPlayer.rank) - self.sex = importedPlayer.male ? 1 : 0 + self.sex = importedPlayer.male ? .male : .female self.tournamentPlayed = importedPlayer.tournamentPlayed self.points = importedPlayer.getPoints() self.clubName = importedPlayer.clubName @@ -74,14 +74,14 @@ class PlayerRegistration: ModelObject, Storable { source = .beachPadel if sexUnknown { if sex == 1 && FileImportManager.shared.foundInWomenData(license: federalData[3]) { - self.sex = 0 + self.sex = .female } else if FileImportManager.shared.foundInMenData(license: federalData[3]) { - self.sex = 1 + self.sex = .male } else { - self.sex = -1 + self.sex = nil } } else { - self.sex = sex + self.sex = PlayerSexType(rawValue: sex) } } @@ -243,7 +243,7 @@ class PlayerRegistration: ModelObject, Storable { } func isMalePlayer() -> Bool { - sex == 1 + sex == .male } func validateLicenceId(_ year: Int) { @@ -284,7 +284,7 @@ class PlayerRegistration: ModelObject, Storable { case beachPadel = 1 } - enum PlayerSexType: Int, CaseIterable, Identifiable, Codable { + enum PlayerSexType: Int, Hashable, CaseIterable, Identifiable, Codable { init?(rawValue: Int?) { guard let value = rawValue else { return nil } self.init(rawValue: value) diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 8d2f3a2..0c6bdb7 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -244,7 +244,7 @@ class TeamRegistration: ModelObject, Storable { func players() -> [PlayerRegistration] { Store.main.filter { $0.teamRegistration == self.id }.sorted { (lhs, rhs) in let predicates: [AreInIncreasingOrder] = [ - { $0.sex < $1.sex }, + { $0.sex?.rawValue ?? 0 < $1.sex?.rawValue ?? 0 }, { $0.rank ?? 0 < $1.rank ?? 0 }, { $0.lastName < $1.lastName}, { $0.firstName < $1.firstName } @@ -278,7 +278,7 @@ class TeamRegistration: ModelObject, Storable { func missingPlayerType(inTournamentCategory tournamentCategory: TournamentCategory) -> [Int] { let players = unsortedPlayers() if players.count >= 2 { return [] } - let s = players.map { $0.sex } + let s = players.compactMap { $0.sex?.rawValue } var missing = tournamentCategory.mandatoryPlayerType() s.forEach { i in if let index = missing.firstIndex(of: i) { diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 918a6c1..ef879c5 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -32,7 +32,6 @@ class Tournament : ModelObject, Storable { var federalLevelCategory: TournamentLevel var federalAgeCategory: FederalTournamentAge var groupStageCourtCount: Int? - var seedCount: Int var closedRegistrationDate: Date? var groupStageAdditionalQualified: Int var courtCount: Int = 2 @@ -48,7 +47,7 @@ class Tournament : ModelObject, Storable { @ObservationIgnored var navigationPath: [Screen] = [] - internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = true, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, seedCount: Int = 8, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil) { + internal init(event: String? = nil, name: String? = nil, startDate: Date = Date(), endDate: Date? = nil, creationDate: Date = Date(), isPrivate: Bool = true, groupStageFormat: MatchFormat? = nil, roundFormat: MatchFormat? = nil, loserRoundFormat: MatchFormat? = nil, groupStageSortMode: GroupStageOrderingMode, groupStageCount: Int = 4, rankSourceDate: Date? = nil, dayDuration: Int = 1, teamCount: Int = 24, teamSorting: TeamSortingType? = nil, federalCategory: TournamentCategory, federalLevelCategory: TournamentLevel, federalAgeCategory: FederalTournamentAge, groupStageCourtCount: Int? = nil, closedRegistrationDate: Date? = nil, groupStageAdditionalQualified: Int = 0, courtCount: Int = 2, prioritizeClubMembers: Bool = false, qualifiedPerGroupStage: Int = 1, teamsPerGroupStage: Int = 4, entryFee: Double? = nil) { self.event = event self.name = name self.startDate = startDate @@ -68,7 +67,6 @@ class Tournament : ModelObject, Storable { self.federalLevelCategory = federalLevelCategory self.federalAgeCategory = federalAgeCategory self.groupStageCourtCount = groupStageCourtCount - self.seedCount = seedCount self.closedRegistrationDate = closedRegistrationDate self.groupStageAdditionalQualified = groupStageAdditionalQualified self.courtCount = courtCount @@ -563,7 +561,7 @@ class Tournament : ModelObject, Storable { 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 == -1 }) + let problematicPlayers : [PlayerRegistration] = players.filter({ $0.sex == nil }) let inadequatePlayers : [PlayerRegistration] = inadequatePlayers(in: players) let playersWithoutValidLicense : [PlayerRegistration] = playersWithoutValidLicense(in: players) let playersMissing : [TeamRegistration] = selectedTeams.filter({ $0.unsortedPlayers().count < 2 }) @@ -697,7 +695,7 @@ class Tournament : ModelObject, Storable { let dataURLs = SourceFileManager.shared.allFiles.filter({ $0.dateFromPath == newDate }) let sources = dataURLs.map { CSVParser(url: $0) } - try await player.updateRank(from: sources, lastRank: (player.sex == 0 ? lastRankWoman : lastRankMan) ?? 0) + try await player.updateRank(from: sources, lastRank: (player.sex == .female ? lastRankWoman : lastRankMan) ?? 0) } } @@ -1286,7 +1284,6 @@ extension Tournament { case _federalLevelCategory = "federalLevelCategory" case _federalAgeCategory = "federalAgeCategory" case _groupStageCourtCount = "groupStageCourtCount" - case _seedCount = "seedCount" case _closedRegistrationDate = "closedRegistrationDate" case _groupStageAdditionalQualified = "groupStageAdditionalQualified" case _courtCount = "courtCount" @@ -1365,7 +1362,7 @@ extension Tournament { } static func fake() -> Tournament { - return Tournament(event: "Roland Garros", name: "Magic P100", startDate: Date(), endDate: Date(), creationDate: Date(), isPrivate: false, groupStageFormat: .nineGames, roundFormat: nil, loserRoundFormat: nil, groupStageSortMode: .snake, groupStageCount: 4, rankSourceDate: nil, dayDuration: 2, teamCount: 24, teamSorting: .rank, federalCategory: .men, federalLevelCategory: .p100, federalAgeCategory: .a45, groupStageCourtCount: nil, seedCount: 8, closedRegistrationDate: nil, groupStageAdditionalQualified: 0, courtCount: 4, prioritizeClubMembers: false, qualifiedPerGroupStage: 2, teamsPerGroupStage: 4, entryFee: nil) + return Tournament(event: "Roland Garros", name: "Magic P100", startDate: Date(), endDate: Date(), creationDate: Date(), isPrivate: false, groupStageFormat: .nineGames, roundFormat: nil, loserRoundFormat: nil, groupStageSortMode: .snake, groupStageCount: 4, rankSourceDate: nil, dayDuration: 2, teamCount: 24, teamSorting: .rank, federalCategory: .men, federalLevelCategory: .p100, federalAgeCategory: .a45, groupStageCourtCount: nil, closedRegistrationDate: nil, groupStageAdditionalQualified: 0, courtCount: 4, prioritizeClubMembers: false, qualifiedPerGroupStage: 2, teamsPerGroupStage: 4, entryFee: nil) } } diff --git a/PadelClub/Data/User.swift b/PadelClub/Data/User.swift index 96e2e49..1626594 100644 --- a/PadelClub/Data/User.swift +++ b/PadelClub/Data/User.swift @@ -27,15 +27,6 @@ class User: UserBase { var lastName: String var phone: String? var country: String? - var callMessageBody : String? = nil - var callMessageSignature: String? = nil - var callDisplayFormat: Bool = false - var callDisplayEntryFee: Bool = false - var callUseFullCustomMessage: Bool = false - var matchFormatsDefaultDuration: [MatchFormat: Int]? = nil - var bracketMatchFormatPreference: MatchFormat? - var groupStageMatchFormatPreference: MatchFormat? - var loserBracketMatchFormatPreference: MatchFormat? init(username: String, email: String, firstName: String, lastName: String, phone: String?, country: String?) { self.username = username @@ -73,15 +64,6 @@ class User: UserBase { case _lastName = "lastName" case _phone = "phone" case _country = "country" - case _callMessageBody = "callMessageBody" - case _callMessageSignature = "callMessageSignature" - case _callDisplayFormat = "callDisplayFormat" - case _callDisplayEntryFee = "callDisplayEntryFee" - case _callUseFullCustomMessage = "callUseFullCustomMessage" - case _matchFormatsDefaultDuration = "matchFormatsDefaultDuration" - case _bracketMatchFormatPreference = "bracketMatchFormatPreference" - case _groupStageMatchFormatPreference = "groupStageMatchFormatPreference" - case _loserBracketMatchFormatPreference = "loserBracketMatchFormatPreference" } } diff --git a/PadelClub/ViewModel/AgendaDestination.swift b/PadelClub/ViewModel/AgendaDestination.swift index ba19f71..18982e8 100644 --- a/PadelClub/ViewModel/AgendaDestination.swift +++ b/PadelClub/ViewModel/AgendaDestination.swift @@ -61,6 +61,8 @@ enum AgendaDestination: CaseIterable, Identifiable, Selectable { switch self { case .history: return .green + case .tenup: + return .logoBackground default: return nil } diff --git a/PadelClub/Views/Player/Components/PlayerPopoverView.swift b/PadelClub/Views/Player/Components/PlayerPopoverView.swift index 10da49b..18974c1 100644 --- a/PadelClub/Views/Player/Components/PlayerPopoverView.swift +++ b/PadelClub/Views/Player/Components/PlayerPopoverView.swift @@ -246,7 +246,7 @@ struct PlayerPopoverView: View { } func createManualPlayer() { - let playerRegistration = PlayerRegistration(firstName: firstName, lastName: lastName, licenceId: license.trimmed.isEmpty ? nil : license, rank: rank, sex: sex) + let playerRegistration = PlayerRegistration(firstName: firstName, lastName: lastName, licenceId: license.trimmed.isEmpty ? nil : license, rank: rank, sex: PlayerRegistration.PlayerSexType(rawValue: sex)) self.creationCompletionHandler(playerRegistration) } diff --git a/PadelClub/Views/Player/Components/PlayerSexPickerView.swift b/PadelClub/Views/Player/Components/PlayerSexPickerView.swift index e3b3d38..b81e27e 100644 --- a/PadelClub/Views/Player/Components/PlayerSexPickerView.swift +++ b/PadelClub/Views/Player/Components/PlayerSexPickerView.swift @@ -17,8 +17,8 @@ struct PlayerSexPickerView: View { Text(player.playerLabel()) Spacer() Picker(selection: $player.sex) { - Text("Homme").tag(1 as Int) - Text("Femme").tag(0 as Int) + Text("Homme").tag(PlayerRegistration.PlayerSexType.male) + Text("Femme").tag(PlayerRegistration.PlayerSexType.female) } label: { } diff --git a/PadelClub/Views/Tournament/Screen/Components/InscriptionInfoView.swift b/PadelClub/Views/Tournament/Screen/Components/InscriptionInfoView.swift index 8b95ae2..24f6eeb 100644 --- a/PadelClub/Views/Tournament/Screen/Components/InscriptionInfoView.swift +++ b/PadelClub/Views/Tournament/Screen/Components/InscriptionInfoView.swift @@ -20,7 +20,7 @@ struct InscriptionInfoView: View { var waitingList : [TeamRegistration] { tournament.waitingListTeams(in: selectedTeams) } var duplicates : [PlayerRegistration] { tournament.duplicates(in: players) } - var problematicPlayers : [PlayerRegistration] { players.filter({ $0.sex == -1 }) } + var problematicPlayers : [PlayerRegistration] { players.filter({ $0.sex == nil }) } var inadequatePlayers : [PlayerRegistration] { tournament.inadequatePlayers(in: players) } var playersWithoutValidLicense : [PlayerRegistration] { tournament.playersWithoutValidLicense(in: players) } var entriesFromBeachPadel : [TeamRegistration] { tournament.unsortedTeams().filter({ $0.isImported() }) } From 1caa33182d4c7f6bdf3aa16af379160ceae9b0ee Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Thu, 2 May 2024 19:24:51 +0200 Subject: [PATCH 4/6] update build version, first testflight version --- PadelClub.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index c1f13cc..bd10939 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1810,7 +1810,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1845,7 +1845,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; From 718e51b3246e6a252b80a7907bae6ea60a41f49a Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Fri, 3 May 2024 09:24:47 +0200 Subject: [PATCH 5/6] improvement on fortune wheel --- PadelClub/Data/Match.swift | 8 +- PadelClub/Data/PlayerRegistration.swift | 10 +- PadelClub/Data/TeamRegistration.swift | 2 +- PadelClub/Data/Tournament.swift | 12 ++ PadelClub/Extensions/String+Extensions.swift | 38 ++++--- PadelClub/ViewModel/AgendaDestination.swift | 2 +- .../Views/Components/FortuneWheelView.swift | 107 ++++++++++++------ .../Components/GroupStageTeamView.swift | 41 +++++-- PadelClub/Views/Round/RoundView.swift | 19 +++- PadelClub/Views/Round/RoundsView.swift | 2 +- .../Tournament/Screen/BroadcastView.swift | 8 +- 11 files changed, 178 insertions(+), 71 deletions(-) diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index de0a683..d2e29a3 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -56,11 +56,11 @@ class Match: ModelObject, Storable { } func matchWarningSubject() -> String { - [roundTitle(), matchTitle()].compacted().joined(separator: " ") + [roundTitle(), matchTitle(.short)].compacted().joined(separator: " ") } func matchWarningMessage() -> String { - [roundTitle(), matchTitle(), startDate?.localizedDate(), courtName()].compacted().joined(separator: "\n") + [roundTitle(), matchTitle(.short), startDate?.localizedDate(), courtName()].compacted().joined(separator: "\n") } func matchTitle(_ displayStyle: DisplayStyle = .wide) -> String { @@ -448,6 +448,10 @@ class Match: ModelObject, Storable { endDate ?? .distantFuture } + func hasSpaceLeft() -> Bool { + teams().count == 1 + } + func isReady() -> Bool { teams().count == 2 } diff --git a/PadelClub/Data/PlayerRegistration.swift b/PadelClub/Data/PlayerRegistration.swift index 74d7196..4654725 100644 --- a/PadelClub/Data/PlayerRegistration.swift +++ b/PadelClub/Data/PlayerRegistration.swift @@ -139,9 +139,15 @@ class PlayerRegistration: ModelObject, Storable { func playerLabel(_ displayStyle: DisplayStyle = .wide) -> String { switch displayStyle { case .wide: - lastName.trimmed.capitalized + " " + firstName.trimmed.capitalized + return lastName.trimmed.capitalized + " " + firstName.trimmed.capitalized case .short: - lastName.trimmed.capitalized + " " + firstName.trimmed.prefix(1).capitalized + "." + let names = lastName.components(separatedBy: .whitespaces) + if lastName.components(separatedBy: .whitespaces).count > 1 { + if let firstLongWord = names.first(where: { $0.count > 3 }) { + return firstLongWord.trimmed.capitalized.trunc(length: 10) + " " + firstName.trimmed.prefix(1).capitalized + "." + } + } + return lastName.trimmed.capitalized.trunc(length: 10) + " " + firstName.trimmed.prefix(1).capitalized + "." } } diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 0c6bdb7..1f5f52d 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -123,7 +123,7 @@ class TeamRegistration: ModelObject, Storable { case .wide: players().map { $0.playerLabel(displayStyle) }.joined(separator: " & ") case .short: - players().map { $0.playerLabel(.wide) }.joined(separator: "\n") + players().map { $0.playerLabel(.short) }.joined(separator: "\n") } } diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index ef879c5..1b274c0 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -328,6 +328,10 @@ class Tournament : ModelObject, Storable { let groupStages = groupStages() return groupStages.filter({ $0.hasStarted() && $0.hasEnded() == false }).sorted(by: \.index).first ?? groupStages.first } + + func matchesWithSpace() -> [Match] { + getActiveRound()?.playedMatches().filter({ $0.hasSpaceLeft() }) ?? [] + } func getActiveRound(withSeeds: Bool = false) -> Round? { let rounds = rounds() @@ -979,6 +983,14 @@ class Tournament : ModelObject, Storable { selectedSortedTeams().firstIndex(where: { $0.id == team.id }) } + func labelIndexOf(team: TeamRegistration) -> String? { + if let teamIndex = indexOf(team: team) { + return "#" + (teamIndex + 1).formatted() + } else { + return nil + } + } + func addTeam(_ players: Set, registrationDate: Date? = nil) -> TeamRegistration { let team = TeamRegistration(tournament: id, registrationDate: registrationDate ?? Date()) team.setWeight(from: Array(players), inTournamentCategory: tournamentCategory) diff --git a/PadelClub/Extensions/String+Extensions.swift b/PadelClub/Extensions/String+Extensions.swift index b515c10..f0afc3a 100644 --- a/PadelClub/Extensions/String+Extensions.swift +++ b/PadelClub/Extensions/String+Extensions.swift @@ -7,7 +7,12 @@ import Foundation +// MARK: - Trimming and stuff extension String { + func trunc(length: Int, trailing: String = "…") -> String { + return (self.count > length) ? self.prefix(length) + trailing : self + } + var trimmed: String { trimmingCharacters(in: .whitespacesAndNewlines) } @@ -29,6 +34,7 @@ extension String { } } +// MARK: - Club Name extension String { func acronym() -> String { let acronym = canonicalVersion.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines) @@ -58,16 +64,8 @@ extension String { } } +// MARK: - FFT License extension String { - enum RegexStatic { - static let mobileNumber = /^0[6-7]/ - //static let mobileNumber = /^(?:(?:\+|00)33[\s.-]{0,3}(?:\(0\)[\s.-]{0,3})?|0)[1-9](?:(?:[\s.-]?\d{2}){4}|\d{2}(?:[\s.-]?\d{3}){2})$/ - } - - func isMobileNumber() -> Bool { - firstMatch(of: RegexStatic.mobileNumber) != nil - } - var computedLicense: String { if let licenseKey { return self + licenseKey @@ -138,20 +136,24 @@ extension String { } return nil } -} -extension String { func licencesFound() -> [String] { let matches = self.matches(of: /[1-9][0-9]{5,7}/) return matches.map { String(self[$0.range]) } } } -extension LosslessStringConvertible { - var string: String { .init(self) } -} - +// MARK: - FFT Source Importing extension String { + enum RegexStatic { + static let mobileNumber = /^0[6-7]/ + //static let mobileNumber = /^(?:(?:\+|00)33[\s.-]{0,3}(?:\(0\)[\s.-]{0,3})?|0)[1-9](?:(?:[\s.-]?\d{2}){4}|\d{2}(?:[\s.-]?\d{3}){2})$/ + } + + func isMobileNumber() -> Bool { + firstMatch(of: RegexStatic.mobileNumber) != nil + } + //april 04-2024 bug with accent characters / adobe / fft mutating func replace(characters: [(Character, Character)]) { for (targetChar, replacementChar) in characters { @@ -160,7 +162,13 @@ extension String { } } +// MARK: - Player Names extension StringProtocol { var firstUppercased: String { prefix(1).uppercased() + dropFirst() } var firstCapitalized: String { prefix(1).capitalized + dropFirst() } } + +// MARK: - todo clean up ?? +extension LosslessStringConvertible { + var string: String { .init(self) } +} diff --git a/PadelClub/ViewModel/AgendaDestination.swift b/PadelClub/ViewModel/AgendaDestination.swift index 18982e8..e4a43af 100644 --- a/PadelClub/ViewModel/AgendaDestination.swift +++ b/PadelClub/ViewModel/AgendaDestination.swift @@ -53,7 +53,7 @@ enum AgendaDestination: CaseIterable, Identifiable, Selectable { case .history: DataStore.shared.tournaments.filter { $0.endDate != nil && FederalDataViewModel.shared.isTournamentValidForFilters($0) }.count case .tenup: - FederalDataViewModel.shared.filteredFederalTournaments.count + FederalDataViewModel.shared.filteredFederalTournaments.map { $0.tournaments.count }.reduce(0,+) } } diff --git a/PadelClub/Views/Components/FortuneWheelView.swift b/PadelClub/Views/Components/FortuneWheelView.swift index c31a452..41a9e22 100644 --- a/PadelClub/Views/Components/FortuneWheelView.swift +++ b/PadelClub/Views/Components/FortuneWheelView.swift @@ -8,24 +8,35 @@ import SwiftUI protocol SpinDrawable { - func segmentLabel() -> String + func segmentLabel(_ displayStyle: DisplayStyle) -> [String] } extension String: SpinDrawable { - func segmentLabel() -> String { - self + func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { + [self] } } extension Match: SpinDrawable { - func segmentLabel() -> String { - self.matchTitle(.wide) + func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { + let teams = teams() + if teams.count == 1 { + return teams.first!.segmentLabel(displayStyle) + } else { + return [roundTitle(), matchTitle(displayStyle)].compactMap { $0 } + } } } extension TeamRegistration: SpinDrawable { - func segmentLabel() -> String { - self.teamLabel(.short) + func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { + var strings: [String] = [] + let indexLabel = tournamentObject()?.labelIndexOf(team: self) + if let indexLabel { + strings.append(indexLabel) + } + strings.append(contentsOf: self.players().map { $0.playerLabel(displayStyle) }) + return strings } } @@ -40,15 +51,14 @@ struct DrawOption: Identifiable, SpinDrawable { let initialIndex: Int let option: SpinDrawable - func segmentLabel() -> String { - option.segmentLabel() + func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { + option.segmentLabel(displayStyle) } } struct SpinDrawView: View { @Environment(\.dismiss) private var dismiss - let time: Date = Date() let drawees: [any SpinDrawable] @State var segments: [any SpinDrawable] let completion: ([DrawResult]) -> Void // Completion closure @@ -56,29 +66,20 @@ struct SpinDrawView: View { @State private var drawCount: Int = 0 @State private var draws: [DrawResult] = [DrawResult]() @State private var drawOptions: [DrawOption] = [DrawOption]() - + @State private var selectedIndex: Int? + var autoMode: Bool { drawees.count > 1 } - - func validationLabel(drawee: Int, result: SpinDrawable) -> String { - let draw = drawees[drawee] - return draw.segmentLabel() + " -> " + result.segmentLabel() - } - @State private var selectedIndex: Int? var body: some View { List { - Section { - Text(time.formatted(date: .complete, time: .complete)) - Text(time, style: .timer) - } - if selectedIndex != nil { Section { - Text(validationLabel(drawee: drawCount, result: segments[draws.last!.drawIndex])) + _validationLabelView(drawee: drawCount, result: segments[draws.last!.drawIndex]) if autoMode == false || drawCount == drawees.count { - RowButtonView("ok") { + RowButtonView("Valider le tirage") { + completion(draws) dismiss() } } else { @@ -87,15 +88,15 @@ struct SpinDrawView: View { } } else if drawCount < drawees.count { Section { - Text(drawees[drawCount].segmentLabel()) + _segmentLabelView(segment: drawees[drawCount].segmentLabel(.wide), horizontalAlignment: .center) } Section { - FortuneWheelTestView(segments: drawOptions, autoMode: autoMode) { index in + FortuneWheelContainerView(segments: drawOptions, autoMode: autoMode) { index in self.selectedIndex = index self.draws.append(DrawResult(drawee: drawCount, drawIndex: drawOptions[index].initialIndex)) self.drawOptions.remove(at: index) - + if autoMode && drawCount < drawees.count { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.drawCount += 1 @@ -117,7 +118,7 @@ struct SpinDrawView: View { Section { Text("Tous les tirages sont terminés") ForEach(draws) { drawResult in - Text(validationLabel(drawee: drawResult.drawee, result: segments[drawResult.drawIndex])) + _validationLabelView(drawee: drawResult.drawee, result: segments[drawResult.drawIndex]) } } @@ -135,6 +136,18 @@ struct SpinDrawView: View { Text("Comité du tournoi") } } + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Annuler", role: .cancel) { + dismiss() + } + } + } + .navigationBarBackButtonHidden() + .navigationTitle("Tirage au sort") + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + .toolbar(.hidden, for: .tabBar) .listStyle(.insetGrouped) .scrollDisabled(true) .onAppear { @@ -143,9 +156,29 @@ struct SpinDrawView: View { } } } + + + private func _segmentLabelView(segment: [String], horizontalAlignment: HorizontalAlignment = .leading) -> some View { + VStack(alignment: horizontalAlignment, spacing: 0.0) { + ForEach(segment, id: \.self) { string in + Text(string) + .frame(maxWidth: .infinity) + } + } + } + + @ViewBuilder + private func _validationLabelView(drawee: Int, result: SpinDrawable) -> some View { + HStack(spacing: 0.0) { + let draw = drawees[drawee] + _segmentLabelView(segment: draw.segmentLabel(.wide), horizontalAlignment: .leading) + Image(systemName: "arrowshape.forward.fill") + _segmentLabelView(segment: result.segmentLabel(.wide), horizontalAlignment: .trailing) + } + } } -struct FortuneWheelTestView: View { +struct FortuneWheelContainerView: View { @State private var rotation: Double = 0 let segments: [any SpinDrawable] let autoMode: Bool @@ -162,7 +195,6 @@ struct FortuneWheelTestView: View { .stroke(Color.black, lineWidth: 2) .frame(width: 20, height: 20) .rotationEffect(.degrees(180)) - } .onAppear { if autoMode { @@ -186,7 +218,6 @@ struct FortuneWheelTestView: View { } func rollWheel() { - rotation = 0 // Generate a random angle for the wheel to rotate @@ -249,10 +280,16 @@ struct FortuneWheelView: View { } .fill(getColor(forIndex:index)) - Text(segments[index].segmentLabel()).multilineTextAlignment(.trailing) - .rotationEffect(.degrees(Double(index) * (360 / Double(segments.count)) + (360 / Double(segments.count) / 2))) - .foregroundColor(.white) - .position(arcPosition(index: index, radius: radius)) + VStack(alignment: .trailing, spacing: 0.0) { + let strings = segments[index].segmentLabel(.short) + ForEach(strings, id: \.self) { string in + Text(string).bold() + } + } + .padding(.trailing, 30) + .rotationEffect(.degrees(Double(index) * (360 / Double(segments.count)) + (360 / Double(segments.count) / 2))) + .foregroundColor(.white) + .position(arcPosition(index: index, radius: radius)) } } } diff --git a/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift b/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift index afd06f7..01e3d1d 100644 --- a/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift +++ b/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift @@ -22,11 +22,30 @@ struct GroupStageTeamView: View { } if groupStage.tournamentObject()?.hasEnded() == false { - Section { - NavigationLink { - GroupStageTeamReplacementView(team: team) - } label: { - Text("Chercher à remplacer") + if team.qualified && team.bracketPosition == nil, let tournament = team.tournamentObject() { + Section { + NavigationLink { + SpinDrawView(drawees: [team], segments: tournament.matchesWithSpace()) { results in + + } + } label: { + Text("Tirage au sort visuel") + } + } + + Section { + RowButtonView("Tirage au sort automatique", role: .destructive) { + } + } + } + + if team.qualified == false { + Section { + NavigationLink { + GroupStageTeamReplacementView(team: team) + } label: { + Text("Chercher à remplacer") + } } } @@ -46,11 +65,13 @@ struct GroupStageTeamView: View { } } - Section { - RowButtonView("Retirer de la poule", role: .destructive) { - team.groupStagePosition = nil - team.groupStage = nil - _save() + if team.qualified == false { + Section { + RowButtonView("Retirer de la poule", role: .destructive) { + team.groupStagePosition = nil + team.groupStage = nil + _save() + } } } } diff --git a/PadelClub/Views/Round/RoundView.swift b/PadelClub/Views/Round/RoundView.swift index 4fba924..2998506 100644 --- a/PadelClub/Views/Round/RoundView.swift +++ b/PadelClub/Views/Round/RoundView.swift @@ -18,7 +18,9 @@ struct RoundView: View { List { let loserRounds = round.loserRounds() - + let availableQualifiedTeams = tournament.availableQualifiedTeams() + let displayableMatches = round.displayableMatches() + let spaceLeft = displayableMatches.filter({ $0.hasSpaceLeft() }) if isEditingTournamentSeed.wrappedValue == false { //(where: { $0.isDisabled() == false || isEditingTournamentSeed.wrappedValue }) if loserRounds.isEmpty == false { @@ -33,6 +35,19 @@ struct RoundView: View { } } } + } else if availableQualifiedTeams.isEmpty == false && spaceLeft.isEmpty == false { + NavigationLink("Tirer au sort la position d'un qualifié") { + SpinDrawView(drawees: availableQualifiedTeams, segments: spaceLeft) { results in + results.forEach { drawResult in + print(availableQualifiedTeams[drawResult.drawee].teamLabel()) + print(spaceLeft[drawResult.drawIndex].matchTitle()) + availableQualifiedTeams[drawResult.drawee].setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true) + } + try? dataStore.matches.addOrUpdate(contentOfs: spaceLeft) + try? dataStore.teamRegistrations.addOrUpdate(contentOfs: availableQualifiedTeams) + isEditingTournamentSeed.wrappedValue.toggle() + } + } } else if let availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: round.index) { RowButtonView("Placer \(availableSeedGroup.localizedLabel())" + ((availableSeedGroup.isFixed() == false) ? " au hasard" : "")) { @@ -62,7 +77,7 @@ struct RoundView: View { } } - ForEach(round.displayableMatches()) { match in + ForEach(displayableMatches) { match in Section { MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle) } header: { diff --git a/PadelClub/Views/Round/RoundsView.swift b/PadelClub/Views/Round/RoundsView.swift index db3b83d..76df209 100644 --- a/PadelClub/Views/Round/RoundsView.swift +++ b/PadelClub/Views/Round/RoundsView.swift @@ -15,7 +15,7 @@ struct RoundsView: View { init(tournament: Tournament) { self.tournament = tournament _selectedRound = State(wrappedValue: tournament.getActiveRound()) - if tournament.availableSeeds().isEmpty == false { + if tournament.availableSeeds().isEmpty == false || tournament.availableQualifiedTeams().isEmpty == false { _isEditingTournamentSeed = State(wrappedValue: true) } } diff --git a/PadelClub/Views/Tournament/Screen/BroadcastView.swift b/PadelClub/Views/Tournament/Screen/BroadcastView.swift index 5b89cf0..6351a46 100644 --- a/PadelClub/Views/Tournament/Screen/BroadcastView.swift +++ b/PadelClub/Views/Tournament/Screen/BroadcastView.swift @@ -126,9 +126,13 @@ struct BroadcastView: View { Label("Partager le lien", systemImage: "link") } } label: { - Text("lien") - .underline() + HStack { + Spacer() + Text("lien") + .underline() + } } + .frame(maxWidth: .infinity) .buttonStyle(.borderless) } From 16e229ed1bae4c991549f3c170c3fb715b3da3ea Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Fri, 3 May 2024 09:25:19 +0200 Subject: [PATCH 6/6] build 4 --- PadelClub.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index bd10939..7d15d0c 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -1810,7 +1810,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6; @@ -1845,7 +1845,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_TEAM = BQ3Y44M3Q6;