diff --git a/PadelClub/Data/GroupStage.swift b/PadelClub/Data/GroupStage.swift index 78f349d..0998547 100644 --- a/PadelClub/Data/GroupStage.swift +++ b/PadelClub/Data/GroupStage.swift @@ -80,6 +80,7 @@ class GroupStage: ModelObject, Storable { var _matches = [Match]() for i in 0..<_numberOfMatchesToBuild() { let newMatch = Match(groupStage: id, index: i, matchFormat: matchFormat, name: localizedMatchUpLabel(for: i)) + newMatch.updateTeamScores() _matches.append(newMatch) } @@ -104,6 +105,7 @@ class GroupStage: ModelObject, Storable { for (index, team) in teams.enumerated() { team.qualified = index < tournament.qualifiedPerGroupStage if team.bracketPosition != nil && team.qualified == false { + tournamentObject()?.resetTeamScores(in: team.bracketPosition) team.bracketPosition = nil } } @@ -224,7 +226,7 @@ class GroupStage: ModelObject, Storable { } private func _removeMatches() { - try? deleteDependencies() + try? DataStore.shared.matches.delete(contentOfs: _matches()) } private func _numberOfMatchesToBuild() -> Int { diff --git a/PadelClub/Data/Match.swift b/PadelClub/Data/Match.swift index 7856756..5738e59 100644 --- a/PadelClub/Data/Match.swift +++ b/PadelClub/Data/Match.swift @@ -58,7 +58,7 @@ class Match: ModelObject, Storable { func indexInRound() -> Int { if groupStage != nil { return index - } else if let index = roundObject?.playedMatches().firstIndex(where: { $0.id == id }) { + } else if let index = roundObject?.playedMatches().sorted(by: \.index).firstIndex(where: { $0.id == id }) { return index } return RoundRule.matchIndexWithinRound(fromMatchIndex: index) @@ -400,6 +400,7 @@ class Match: ModelObject, Storable { losingTeamId = teamScoreWalkout.teamRegistration groupStageObject?.updateGroupStageState() roundObject?.updateTournamentState() + updateFollowingMatchTeamScore() } func setScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) { @@ -411,6 +412,7 @@ class Match: ModelObject, Storable { losingTeamId = team(matchDescriptor.winner.otherTeam)?.id groupStageObject?.updateGroupStageState() roundObject?.updateTournamentState() + updateFollowingMatchTeamScore() } func updateScore(fromMatchDescriptor matchDescriptor: MatchDescriptor) { @@ -422,6 +424,39 @@ class Match: ModelObject, Storable { matchFormat = matchDescriptor.matchFormat } + func updateFollowingMatchTeamScore() { + followingMatch()?.updateTeamScores() + _loserMatch()?.updateTeamScores() + } + + func resetTeamScores() { + let teamScores = teamScores + if teamScores.isEmpty == false { + do { + try DataStore.shared.teamScores.delete(contentOfs: teamScores) + } catch { + Logger.error(error) + } + } + followingMatch()?.resetTeamScores() + _loserMatch()?.resetTeamScores() + } + + func updateTeamScores() { + resetTeamScores() + let teamOne = team(.one) + let teamTwo = team(.two) + let teams = [teamOne, teamTwo].compactMap({ $0 }).map { TeamScore(match: id, team: $0) } + do { + try DataStore.shared.teamScores.addOrUpdate(contentOfs: teams) + } catch { + Logger.error(error) + } + if teams.isEmpty == false { + updateFollowingMatchTeamScore() + } + } + func validateMatch(fromStartDate: Date, toEndDate: Date, fieldSetup: MatchFieldSetup) { if hasEnded() == false { startDate = fromStartDate diff --git a/PadelClub/Data/TeamRegistration.swift b/PadelClub/Data/TeamRegistration.swift index 7b0de30..4f22611 100644 --- a/PadelClub/Data/TeamRegistration.swift +++ b/PadelClub/Data/TeamRegistration.swift @@ -61,7 +61,9 @@ class TeamRegistration: ModelObject, Storable { func setSeedPosition(inSpot match: Match, slot: TeamPosition?, opposingSeeding: Bool) { let seedPosition = match.lockAndGetSeedPosition(atTeamPosition: slot, opposingSeeding: opposingSeeding) + tournamentObject()?.resetTeamScores(in: bracketPosition) bracketPosition = seedPosition + tournamentObject()?.updateTeamScores(in: bracketPosition) } func expectedSummonDate() -> Date? { @@ -183,8 +185,10 @@ class TeamRegistration: ModelObject, Storable { } func resetPositions() { + groupStageObject()?._matches().forEach({ $0.updateTeamScores() }) groupStage = nil groupStagePosition = nil + tournamentObject()?.resetTeamScores(in: bracketPosition) bracketPosition = nil } diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 0ccceb9..27222ae 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -315,7 +315,7 @@ class Tournament : ModelObject, Storable { return first } } else { - return nil + return startDate } } @@ -336,7 +336,7 @@ class Tournament : ModelObject, Storable { return first } } else { - return nil + return startDate } } @@ -1137,7 +1137,6 @@ class Tournament : ModelObject, Storable { try? DataStore.shared.groupStages.addOrUpdate(contentOfs: _groupStages) - groupStages().forEach { $0.buildMatches() } refreshGroupStages() } @@ -1173,6 +1172,26 @@ class Tournament : ModelObject, Storable { round.buildLoserBracket() } } + + func match(for bracketPosition: Int?) -> Match? { + guard let bracketPosition else { return nil } + let matchIndex = bracketPosition / 2 + let roundIndex = RoundRule.roundIndex(fromMatchIndex: matchIndex) + if let round : Round = Store.main.filter(isIncluded: { $0.tournament == id && $0.index == roundIndex }).first { + return Store.main.filter(isIncluded: { $0.round == round.id && $0.index == matchIndex }).first + } + return nil + } + + func resetTeamScores(in matchOfBracketPosition: Int?) { + guard let match = match(for: matchOfBracketPosition) else { return } + match.resetTeamScores() + } + + func updateTeamScores(in matchOfBracketPosition: Int?) { + guard let match = match(for: matchOfBracketPosition) else { return } + match.updateTeamScores() + } func deleteStructure() { do { @@ -1234,7 +1253,7 @@ class Tournament : ModelObject, Storable { } let max = groupStages.map { $0.size }.reduce(0,+) - var chunks = selectedSortedTeams().suffix(max).chunked(into: numberOfBracketsAsInt) + var chunks = selectedSortedTeams().suffix(max).chunked(into: groupStageCount) for (index, _) in chunks.enumerated() { if randomize { chunks[index].shuffle() @@ -1251,6 +1270,8 @@ class Tournament : ModelObject, Storable { try? DataStore.shared.teamRegistrations.addOrUpdate(instance: chunks[index][jIndex]) } } + + groupStages.forEach { $0.buildMatches() } } diff --git a/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift b/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift index f5ce7b8..c0a6f86 100644 --- a/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift +++ b/PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift @@ -59,6 +59,7 @@ struct GroupStageTeamView: View { } else { RowButtonView("Annuler la qualification", role: .destructive) { team.qualified = false + groupStage.tournamentObject()?.resetTeamScores(in: team.bracketPosition) team.bracketPosition = nil _save() } @@ -71,6 +72,7 @@ struct GroupStageTeamView: View { team.groupStagePosition = nil team.groupStage = nil _save() + groupStage._matches().forEach({ $0.updateTeamScores() }) } } } diff --git a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift index cd6b042..7d3e95b 100644 --- a/PadelClub/Views/GroupStage/GroupStageSettingsView.swift +++ b/PadelClub/Views/GroupStage/GroupStageSettingsView.swift @@ -27,6 +27,15 @@ struct GroupStageSettingsView: View { var body: some View { List { + + #if DEBUG + Section { + RowButtonView("delete all group stages") { + tournament.deleteGroupStages() + } + } + #endif + if tournament.unsortedTeams().filter({ $0.groupStagePosition != nil }).isEmpty == false { Section { menuBuildAllGroupStages diff --git a/PadelClub/Views/GroupStage/GroupStageView.swift b/PadelClub/Views/GroupStage/GroupStageView.swift index 8c61b51..6c79f5c 100644 --- a/PadelClub/Views/GroupStage/GroupStageView.swift +++ b/PadelClub/Views/GroupStage/GroupStageView.swift @@ -163,6 +163,7 @@ struct GroupStageView: View { print(team.pasteData()) team.groupStage = groupStage.id team.groupStagePosition = index + groupStage._matches().forEach({ $0.updateTeamScores() }) do { try dataStore.teamRegistrations.addOrUpdate(instance: team) } catch { @@ -199,6 +200,7 @@ struct GroupStageView: View { teams.forEach { team in team.groupStagePosition = nil team.groupStage = nil + groupStage._matches().forEach({ $0.updateTeamScores() }) } do { try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams) diff --git a/PadelClub/Views/Match/MatchSetupView.swift b/PadelClub/Views/Match/MatchSetupView.swift index c13b58c..f342841 100644 --- a/PadelClub/Views/Match/MatchSetupView.swift +++ b/PadelClub/Views/Match/MatchSetupView.swift @@ -31,8 +31,10 @@ struct MatchSetupView: View { TeamRowView(team: team, teamPosition: teamPosition) .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button(role: .cancel) { + //todo if match.isSeededBy(team: team, inTeamPosition: teamPosition) { team.bracketPosition = nil + match.updateTeamScores() match.enableMatch() try? dataStore.matches.addOrUpdate(instance: match) try? dataStore.teamRegistrations.addOrUpdate(instance: team) diff --git a/PadelClub/Views/Planning/PlanningSettingsView.swift b/PadelClub/Views/Planning/PlanningSettingsView.swift index e36cfaf..66b71be 100644 --- a/PadelClub/Views/Planning/PlanningSettingsView.swift +++ b/PadelClub/Views/Planning/PlanningSettingsView.swift @@ -153,7 +153,7 @@ struct PlanningSettingsView: View { @ViewBuilder private func _optionsView() -> some View { - if tournament.groupStages().isEmpty == false { + if tournament.groupStageCount > 0 { Section { TournamentFieldsManagerView(localizedStringKey: "Poule en parallèle", count: $groupStageChunkCount, max: tournament.groupStageCount) .onChange(of: groupStageChunkCount) { diff --git a/PadelClub/Views/Round/LoserRoundView.swift b/PadelClub/Views/Round/LoserRoundView.swift index 1ed9c82..89e7ca0 100644 --- a/PadelClub/Views/Round/LoserRoundView.swift +++ b/PadelClub/Views/Round/LoserRoundView.swift @@ -27,7 +27,7 @@ struct LoserRoundView: View { ForEach(loserRounds) { loserRound in if isEditingTournamentSeed || loserRound.isDisabled() == false { Section { - let matches = isEditingTournamentSeed ? loserRound.playedMatches() : loserRound.playedMatches().filter({ $0.disabled == false }) + let matches = (isEditingTournamentSeed ? loserRound.playedMatches() : loserRound.playedMatches().filter({ $0.disabled == false })).sorted(by: \.index) ForEach(matches) { match in MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle) .overlay { diff --git a/PadelClub/Views/Round/RoundSettingsView.swift b/PadelClub/Views/Round/RoundSettingsView.swift index b3d5aff..92017b9 100644 --- a/PadelClub/Views/Round/RoundSettingsView.swift +++ b/PadelClub/Views/Round/RoundSettingsView.swift @@ -26,7 +26,10 @@ struct RoundSettingsView: View { // } Section { RowButtonView("Retirer toutes les têtes de séries", role: .destructive) { - tournament.unsortedTeams().forEach({ $0.bracketPosition = nil }) + tournament.unsortedTeams().forEach({ team in + tournament.resetTeamScores(in: team.bracketPosition) + team.bracketPosition = nil + }) try? dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams()) tournament.allRounds().forEach({ round in round.enableRound() diff --git a/PadelClub/Views/Round/RoundView.swift b/PadelClub/Views/Round/RoundView.swift index b7e317d..59fcdde 100644 --- a/PadelClub/Views/Round/RoundView.swift +++ b/PadelClub/Views/Round/RoundView.swift @@ -28,7 +28,7 @@ struct RoundView: View { let loserRounds = round.loserRounds() let availableQualifiedTeams = tournament.availableQualifiedTeams() - let displayableMatches = round.displayableMatches() + let displayableMatches = round.displayableMatches().sorted(by: \.index) let spaceLeft = displayableMatches.filter({ $0.hasSpaceLeft() }) if isEditingTournamentSeed.wrappedValue == false { //(where: { $0.isDisabled() == false || isEditingTournamentSeed.wrappedValue }) diff --git a/PadelClub/Views/Subscription/Guard.swift b/PadelClub/Views/Subscription/Guard.swift index c7e6dd0..3be6e2e 100644 --- a/PadelClub/Views/Subscription/Guard.swift +++ b/PadelClub/Views/Subscription/Guard.swift @@ -145,14 +145,14 @@ import LeStorage } var currentPlan: StoreItem? { -// #if DEBUG -// return nil -// #else + #if DEBUG + return .monthlyUnlimited + #else if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) { return plan } return nil -// #endif + #endif } func userFilteredPurchases() -> [StoreKit.Transaction] { diff --git a/PadelClub/Views/Tournament/TournamentBuildView.swift b/PadelClub/Views/Tournament/TournamentBuildView.swift index b58bbf9..9222004 100644 --- a/PadelClub/Views/Tournament/TournamentBuildView.swift +++ b/PadelClub/Views/Tournament/TournamentBuildView.swift @@ -57,7 +57,7 @@ struct TournamentBuildView: View { } Section { - if tournament.groupStages().isEmpty == false { + if tournament.groupStageCount > 0 { NavigationLink(value: Screen.groupStage) { LabeledContent { Text(tournament.groupStageStatus())