diff --git a/PadelClubData/Data/MatchScheduler.swift b/PadelClubData/Data/MatchScheduler.swift index 5f16a7d..39ed5de 100644 --- a/PadelClubData/Data/MatchScheduler.swift +++ b/PadelClubData/Data/MatchScheduler.swift @@ -838,8 +838,10 @@ final public class MatchScheduler: BaseMatchScheduler, SideStorable { } - if tournament.dayDuration > 1 && (lastDate.timeOfDay == .evening || lastDate.timeOfDay == .night || errorFormat) { - bracketStartDate = lastDate.tomorrowAtNine + if tournament.dayDuration > 1 && (lastDate.timeOfDay == .evening || lastDate.timeOfDay == .night || errorFormat) { + if tournament.groupStageCount > 0 { + bracketStartDate = lastDate.tomorrowAtNine + } } return updateBracketSchedule(tournament: tournament, fromRoundId: nil, fromMatchId: nil, startDate: bracketStartDate) diff --git a/PadelClubData/Data/TeamRegistration.swift b/PadelClubData/Data/TeamRegistration.swift index 865dfaf..cb3ef5c 100644 --- a/PadelClubData/Data/TeamRegistration.swift +++ b/PadelClubData/Data/TeamRegistration.swift @@ -256,7 +256,7 @@ final public class TeamRegistration: BaseTeamRegistration, SideStorable { public func teamLabel( _ displayStyle: DisplayStyle = .wide, twoLines: Bool = false, separator: String = "&" ) -> String { - if let name { return name } + if let name, name.isEmpty == false { return name } return players().map { $0.playerLabel(displayStyle) }.joined( separator: twoLines ? "\n" : " \(separator) ") } diff --git a/PadelClubData/Data/Tournament.swift b/PadelClubData/Data/Tournament.swift index 0fab86a..9c16560 100644 --- a/PadelClubData/Data/Tournament.swift +++ b/PadelClubData/Data/Tournament.swift @@ -345,6 +345,7 @@ defer { public func availableSeedOpponentSpot(inRoundIndex roundIndex: Int) -> [Match] { return getRound(atRoundIndex: roundIndex)?.playedMatches().filter { $0.hasSpaceLeft() } ?? [] } + public func availableSeedGroups(includeAll: Bool = false) -> [SeedInterval] { let seeds = seeds() var availableSeedGroup = Set() @@ -362,6 +363,24 @@ defer { return availableSeedGroup.sorted(by: <) } + public func generateSeedGroups(base: Int, teamCount: Int) -> [SeedInterval] { + let start = base + 1 + let root = SeedInterval(first: start, last: start + teamCount - 1) + var groups: [SeedInterval] = [] + + func split(interval: SeedInterval) { + groups.append(interval) + if let chunks = interval.chunks() { + for chunk in chunks { + split(interval: chunk) + } + } + } + + split(interval: root) + return groups.sorted(by: <) + } + public func chunksBy(in chunks: [SeedInterval], availableSeedGroup: inout Set) { chunks.forEach { chunk in availableSeedGroup.insert(chunk) @@ -1663,12 +1682,14 @@ defer { } public func initSettings(templateTournament: Tournament?, overrideTeamCount: Bool = true) { + courtCount = eventObject()?.clubObject()?.courtCount ?? 2 setupDefaultPrivateSettings(templateTournament: templateTournament) setupUmpireSettings(defaultTournament: nil) //default is not template, default is for event sharing settings if let templateTournament { setupRegistrationSettings(templateTournament: templateTournament, overrideTeamCount: overrideTeamCount) } setupFederalSettings() + customizeUsingPreferences() } public func setupFederalSettings() { @@ -1684,6 +1705,23 @@ defer { } } + public func customizeUsingPreferences() { + guard let lastTournamentWithSameBuild = DataStore.shared.tournaments.filter({ tournament in + tournament.tournamentLevel == self.tournamentLevel + && tournament.tournamentCategory == self.tournamentCategory + && tournament.federalTournamentAge == self.federalTournamentAge + && tournament.hasEnded() == true + && tournament.isCanceled == false + && tournament.isDeleted == false + }).sorted(by: \.endDate!, order: .descending).first else { + return + } + + self.entryFee = lastTournamentWithSameBuild.entryFee + self.clubMemberFeeDeduction = lastTournamentWithSameBuild.clubMemberFeeDeduction + } + + public func deadline(for type: TournamentDeadlineType) -> Date? { guard [.p500, .p1000, .p1500, .p2000].contains(tournamentLevel) else { return nil } diff --git a/PadelClubData/Subscriptions/Guard.swift b/PadelClubData/Subscriptions/Guard.swift index f9951ba..2164667 100644 --- a/PadelClubData/Subscriptions/Guard.swift +++ b/PadelClubData/Subscriptions/Guard.swift @@ -30,11 +30,7 @@ import Combine self.updateListenerTask = self.listenForTransactions() Task { - do { - try await self.refreshPurchasedAppleProducts() - } catch { - Logger.error(error) - } + await self.refreshPurchases() Logger.log("plan = \(String(describing: currentBestPurchase?.productId))") } @@ -66,19 +62,46 @@ import Combine return productIds } - public func refreshPurchasedAppleProducts() async throws { + public func refreshPurchases() async { + await _refreshUnfinishedTransactions() + await _refreshPurchasedAppleProducts() + } + + fileprivate func _refreshPurchasedAppleProducts() async { // Iterate through the user's purchased products. for await verificationResult in Transaction.currentEntitlements { - let transaction = try await self.processTransactionResult(verificationResult) - print("processs product id = \(transaction.productID)") - DispatchQueue.main.async { - NotificationCenter.default.post(name: Notification.Name.StoreEventHappened, object: nil) + do { + let transaction = try await self.processTransactionResult(verificationResult) + print("processs product id = \(transaction.productID)") + DispatchQueue.main.async { + NotificationCenter.default.post(name: Notification.Name.StoreEventHappened, object: nil) + } + await transaction.finish() + } catch { + Logger.error(error) } - await transaction.finish() } } + public func _refreshUnfinishedTransactions() async { + + // Iterate through the user's purchased products. + for await verificationResult in Transaction.unfinished { + do { + let transaction = try await self.processTransactionResult(verificationResult) + print("processs product id = \(transaction.productID)") + DispatchQueue.main.async { + NotificationCenter.default.post(name: Notification.Name.StoreEventHappened, object: nil) + } + await transaction.finish() + } catch { + Logger.error(error) + } + } + } + + func listenForTransactions() -> Task { return Task(priority: .background) { //Iterate through any transactions which didn't come from a direct call to `purchase()`.