From ed0148694ff4ce61c2451f320d43e945418d46df Mon Sep 17 00:00:00 2001 From: Razmig Sarkissian Date: Tue, 14 May 2024 12:04:09 +0200 Subject: [PATCH] add matchscheduler storage object --- PadelClub.xcodeproj/project.pbxproj | 2 +- PadelClub/Data/DataStore.swift | 6 +- .../{ViewModel => Data}/MatchScheduler.swift | 200 ++++++++++-------- PadelClub/Data/Tournament.swift | 9 + .../LoserRoundScheduleEditorView.swift | 2 +- .../LoserRoundStepScheduleEditorView.swift | 2 +- .../Planning/MatchScheduleEditorView.swift | 2 +- .../Views/Planning/PlanningSettingsView.swift | 181 +++++++--------- .../Planning/RoundScheduleEditorView.swift | 2 +- PadelClub/Views/Planning/SchedulerView.swift | 2 +- 10 files changed, 212 insertions(+), 196 deletions(-) rename PadelClub/{ViewModel => Data}/MatchScheduler.swift (88%) diff --git a/PadelClub.xcodeproj/project.pbxproj b/PadelClub.xcodeproj/project.pbxproj index cc109c7..58b0252 100644 --- a/PadelClub.xcodeproj/project.pbxproj +++ b/PadelClub.xcodeproj/project.pbxproj @@ -690,6 +690,7 @@ FF8F263E2BAD7D5C00650388 /* Event.swift */, FF025AE82BD1307E00A86CF8 /* MonthData.swift */, FF1DC5522BAB354A00FD8220 /* MockData.swift */, + FF3B60A22BC49BBC008C2E66 /* MatchScheduler.swift */, FFDB1C6C2BB2A02000F1E467 /* AppSettings.swift */, FFC91B002BD85C2F00B29808 /* Court.swift */, FFF116E02BD2A9B600A33B06 /* DateInterval.swift */, @@ -987,7 +988,6 @@ FFCFC0132BBC59FC00B82851 /* MatchDescriptor.swift */, FFCFC01B2BBC5AAA00B82851 /* SetDescriptor.swift */, FFBF065F2BBD9F6D009D6715 /* NavigationViewModel.swift */, - FF3B60A22BC49BBC008C2E66 /* MatchScheduler.swift */, FF5BAF6D2BE0B3C8008B4B7E /* FederalDataViewModel.swift */, ); path = ViewModel; diff --git a/PadelClub/Data/DataStore.swift b/PadelClub/Data/DataStore.swift index 8dfc8ba..3f47775 100644 --- a/PadelClub/Data/DataStore.swift +++ b/PadelClub/Data/DataStore.swift @@ -42,7 +42,8 @@ class DataStore: ObservableObject { fileprivate(set) var teamScores: StoredCollection fileprivate(set) var monthData: StoredCollection fileprivate(set) var dateIntervals: StoredCollection - + fileprivate(set) var matchSchedulers: StoredCollection + fileprivate(set) var userStorage: StoredSingleton // fileprivate var _userStorage: OptionalStorage = OptionalStorage(fileName: "user.json") @@ -81,7 +82,8 @@ class DataStore: ObservableObject { self.matches = store.registerCollection(synchronized: synchronized, indexed: indexed) self.monthData = store.registerCollection(synchronized: false, indexed: indexed) self.dateIntervals = store.registerCollection(synchronized: synchronized, indexed: indexed) - + self.matchSchedulers = store.registerCollection(synchronized: false, indexed: indexed) + self.userStorage = store.registerObject(synchronized: synchronized) NotificationCenter.default.addObserver(self, selector: #selector(collectionDidLoad), name: NSNotification.Name.CollectionDidLoad, object: nil) diff --git a/PadelClub/ViewModel/MatchScheduler.swift b/PadelClub/Data/MatchScheduler.swift similarity index 88% rename from PadelClub/ViewModel/MatchScheduler.swift rename to PadelClub/Data/MatchScheduler.swift index 85760fc..077ac2b 100644 --- a/PadelClub/ViewModel/MatchScheduler.swift +++ b/PadelClub/Data/MatchScheduler.swift @@ -7,91 +7,71 @@ import Foundation import LeStorage - -struct GroupStageTimeMatch { - let matchID: String - let rotationIndex: Int - var courtIndex: Int - let groupIndex: Int -} - -struct TimeMatch { - let matchID: String - let rotationIndex: Int - var courtIndex: Int - var startDate: Date - var durationLeft: Int //in minutes - var minimumBreakTime: Int //in minutes - - func estimatedEndDate(includeBreakTime: Bool) -> Date { - let minutesToAdd = Double(durationLeft + (includeBreakTime ? minimumBreakTime : 0)) - return startDate.addingTimeInterval(minutesToAdd * 60.0) - } -} - -struct GroupStageMatchDispatcher { - let timedMatches: [GroupStageTimeMatch] - let freeCourtPerRotation: [Int: [Int]] - let rotationCount: Int - let groupLastRotation: [Int: Int] -} - -struct MatchDispatcher { - let timedMatches: [TimeMatch] - let freeCourtPerRotation: [Int: [Int]] - let rotationCount: Int -} - -extension Match { - func teamIds() -> [String] { - return teams().map { $0.id } +import SwiftUI + +@Observable +class MatchScheduler : ModelObject, Storable { + static func resourceName() -> String { return "match-scheduler" } + static func requestsRequiresToken() -> Bool { true } + + private(set) var id: String = Store.randomId() + var tournament: String + var timeDifferenceLimit: Int + var loserBracketRotationDifference: Int + var upperBracketRotationDifference: Int + var accountUpperBracketBreakTime: Bool + var accountLoserBracketBreakTime: Bool + var randomizeCourts: Bool + var rotationDifferenceIsImportant: Bool + var shouldHandleUpperRoundSlice: Bool + var shouldEndRoundBeforeStartingNext: Bool + + init(tournament: String, + timeDifferenceLimit: Int = 5, + loserBracketRotationDifference: Int = 0, + upperBracketRotationDifference: Int = 1, + accountUpperBracketBreakTime: Bool = true, + accountLoserBracketBreakTime: Bool = false, + randomizeCourts: Bool = true, + rotationDifferenceIsImportant: Bool = false, + shouldHandleUpperRoundSlice: Bool = true, + shouldEndRoundBeforeStartingNext: Bool = true) { + self.tournament = tournament + self.timeDifferenceLimit = timeDifferenceLimit + self.loserBracketRotationDifference = loserBracketRotationDifference + self.upperBracketRotationDifference = upperBracketRotationDifference + self.accountUpperBracketBreakTime = accountUpperBracketBreakTime + self.accountLoserBracketBreakTime = accountLoserBracketBreakTime + self.randomizeCourts = randomizeCourts + self.rotationDifferenceIsImportant = rotationDifferenceIsImportant + self.shouldHandleUpperRoundSlice = shouldHandleUpperRoundSlice + self.shouldEndRoundBeforeStartingNext = shouldEndRoundBeforeStartingNext } - func containsTeamId(_ id: String) -> Bool { - teamIds().contains(id) + enum CodingKeys: String, CodingKey { + case _id = "id" + case _tournament = "tournament" + case _timeDifferenceLimit = "timeDifferenceLimit" + case _loserBracketRotationDifference = "loserBracketRotationDifference" + case _upperBracketRotationDifference = "upperBracketRotationDifference" + case _accountUpperBracketBreakTime = "accountUpperBracketBreakTime" + case _accountLoserBracketBreakTime = "accountLoserBracketBreakTime" + case _randomizeCourts = "randomizeCourts" + case _rotationDifferenceIsImportant = "rotationDifferenceIsImportant" + case _shouldHandleUpperRoundSlice = "shouldHandleUpperRoundSlice" + case _shouldEndRoundBeforeStartingNext = "shouldEndRoundBeforeStartingNext" } -} -enum MatchSchedulerOption: Hashable { - case accountUpperBracketBreakTime - case accountLoserBracketBreakTime - case randomizeCourts - case rotationDifferenceIsImportant - case shouldHandleUpperRoundSlice - case shouldEndRoundBeforeStartingNext -} - -class MatchScheduler { - static let shared = MatchScheduler() - var additionalEstimationDuration : Int = 0 - var options: Set = Set(arrayLiteral: .accountUpperBracketBreakTime) - var timeDifferenceLimit: Double = 300.0 - var loserBracketRotationDifference: Int = 0 - var upperBracketRotationDifference: Int = 1 - var courtsUnavailability: [DateInterval]? = nil - - func shouldEndRoundBeforeStartingNext() -> Bool { - options.contains(.shouldEndRoundBeforeStartingNext) + var courtsUnavailability: [DateInterval]? { + tournamentObject()?.eventObject()?.courtsUnavailability } - func shouldHandleUpperRoundSlice() -> Bool { - options.contains(.shouldHandleUpperRoundSlice) + var additionalEstimationDuration : Int { + tournamentObject()?.additionalEstimationDuration ?? 0 } - func accountLoserBracketBreakTime() -> Bool { - options.contains(.accountLoserBracketBreakTime) - } - - func accountUpperBracketBreakTime() -> Bool { - options.contains(.accountUpperBracketBreakTime) - } - - func randomizeCourts() -> Bool { - options.contains(.randomizeCourts) - } - - func rotationDifferenceIsImportant() -> Bool { - options.contains(.rotationDifferenceIsImportant) + func tournamentObject() -> Tournament? { + Store.main.findById(tournament) } @discardableResult @@ -99,7 +79,6 @@ class MatchScheduler { let groupStageCourtCount = tournament.groupStageCourtCount ?? 1 let groupStages = tournament.groupStages() let numberOfCourtsAvailablePerRotation: Int = tournament.courtCount - courtsUnavailability = tournament.eventObject()?.courtsUnavailability let matches = groupStages.flatMap({ $0._matches() }) matches.forEach({ @@ -197,7 +176,7 @@ class MatchScheduler { var organizedSlots = [GroupStageTimeMatch]() for i in 0..= minimumPossibleEndDate { - if rotationDifferenceIsImportant() { + if rotationDifferenceIsImportant { return previousMatchIsInPreviousRotation } else { return true @@ -375,14 +354,15 @@ class MatchScheduler { let differenceWithoutBreak = rotationStartDate.timeIntervalSince(previousEndDateNoBreak) print("difference w break", differenceWithBreak) print("difference w/o break", differenceWithoutBreak) + let timeDifferenceLimitInSeconds = Double(timeDifferenceLimit * 60) var difference = differenceWithBreak if differenceWithBreak <= 0 { difference = differenceWithoutBreak - } else if differenceWithBreak > timeDifferenceLimit && differenceWithoutBreak > timeDifferenceLimit { + } else if differenceWithBreak > timeDifferenceLimitInSeconds && differenceWithoutBreak > timeDifferenceLimitInSeconds { difference = noBreakAlreadyTested ? differenceWithBreak : max(differenceWithBreak, differenceWithoutBreak) } - if difference > timeDifferenceLimit { + if difference > timeDifferenceLimitInSeconds { courts.removeAll(where: { index in freeCourtPreviousRotation.contains(index) }) freeCourtPerRotation[rotationIndex] = courts @@ -399,7 +379,7 @@ class MatchScheduler { var organizedSlots = [TimeMatch]() for i in 0.. courts.count { @@ -502,14 +482,13 @@ class MatchScheduler { } func updateBracketSchedule(tournament: Tournament, fromRoundId roundId: String?, fromMatchId matchId: String?, startDate: Date) { - courtsUnavailability = tournament.eventObject()?.courtsUnavailability let upperRounds = tournament.rounds() let allMatches = tournament.allMatches() var rounds = [Round]() - if shouldEndRoundBeforeStartingNext() { + if shouldEndRoundBeforeStartingNext { rounds = upperRounds.flatMap { [$0] + $0.loserRoundsAndChildren() } @@ -607,8 +586,51 @@ class MatchScheduler { } func updateSchedule(tournament: Tournament) { - courtsUnavailability = tournament.eventObject()?.courtsUnavailability let lastDate = updateGroupStageSchedule(tournament: tournament) updateBracketSchedule(tournament: tournament, fromRoundId: nil, fromMatchId: nil, startDate: lastDate) } } + +struct GroupStageTimeMatch { + let matchID: String + let rotationIndex: Int + var courtIndex: Int + let groupIndex: Int +} + +struct TimeMatch { + let matchID: String + let rotationIndex: Int + var courtIndex: Int + var startDate: Date + var durationLeft: Int //in minutes + var minimumBreakTime: Int //in minutes + + func estimatedEndDate(includeBreakTime: Bool) -> Date { + let minutesToAdd = Double(durationLeft + (includeBreakTime ? minimumBreakTime : 0)) + return startDate.addingTimeInterval(minutesToAdd * 60.0) + } +} + +struct GroupStageMatchDispatcher { + let timedMatches: [GroupStageTimeMatch] + let freeCourtPerRotation: [Int: [Int]] + let rotationCount: Int + let groupLastRotation: [Int: Int] +} + +struct MatchDispatcher { + let timedMatches: [TimeMatch] + let freeCourtPerRotation: [Int: [Int]] + let rotationCount: Int +} + +extension Match { + func teamIds() -> [String] { + return teams().map { $0.id } + } + + func containsTeamId(_ id: String) -> Bool { + teamIds().contains(id) + } +} diff --git a/PadelClub/Data/Tournament.swift b/PadelClub/Data/Tournament.swift index 0447a27..8233ad6 100644 --- a/PadelClub/Data/Tournament.swift +++ b/PadelClub/Data/Tournament.swift @@ -1302,8 +1302,17 @@ class Tournament : ModelObject, Storable { try Store.main.deleteDependencies(items: self.unsortedTeams()) try Store.main.deleteDependencies(items: self.groupStages()) try Store.main.deleteDependencies(items: self.rounds()) + try Store.main.deleteDependencies(items: self._matchSchedulers()) } + private func _matchSchedulers() -> [MatchScheduler] { + Store.main.filter(isIncluded: { $0.id == self.id }) + } + + func matchScheduler() -> MatchScheduler? { + _matchSchedulers().first + } + func currentMonthData() -> MonthData? { guard let rankSourceDate else { return nil } let dateString = URL.importDateFormatter.string(from: rankSourceDate) diff --git a/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift b/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift index 2b35159..63c5eb0 100644 --- a/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift +++ b/PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift @@ -66,7 +66,7 @@ struct LoserRoundScheduleEditorView: View { // _save() let loserRounds = upperRound.loserRounds().filter { $0.isDisabled() == false } - MatchScheduler.shared.updateBracketSchedule(tournament: tournament, fromRoundId: loserRounds.first?.id, fromMatchId: nil, startDate: startDate) + tournament.matchScheduler()?.updateBracketSchedule(tournament: tournament, fromRoundId: loserRounds.first?.id, fromMatchId: nil, startDate: startDate) loserRounds.first?.startDate = startDate _save() } diff --git a/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift b/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift index 1904942..af61798 100644 --- a/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift +++ b/PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift @@ -59,7 +59,7 @@ struct LoserRoundStepScheduleEditorView: View { } private func _updateSchedule() async { - MatchScheduler.shared.updateBracketSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) + tournament.matchScheduler()?.updateBracketSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) upperRound.loserRounds(forRoundIndex: round.index).forEach({ round in round.startDate = startDate }) diff --git a/PadelClub/Views/Planning/MatchScheduleEditorView.swift b/PadelClub/Views/Planning/MatchScheduleEditorView.swift index 7f45a07..6edf190 100644 --- a/PadelClub/Views/Planning/MatchScheduleEditorView.swift +++ b/PadelClub/Views/Planning/MatchScheduleEditorView.swift @@ -33,7 +33,7 @@ struct MatchScheduleEditorView: View { } private func _updateSchedule() async { - MatchScheduler.shared.updateBracketSchedule(tournament: tournament, fromRoundId: match.round, fromMatchId: match.id, startDate: startDate) + tournament.matchScheduler()?.updateBracketSchedule(tournament: tournament, fromRoundId: match.round, fromMatchId: match.id, startDate: startDate) } } diff --git a/PadelClub/Views/Planning/PlanningSettingsView.swift b/PadelClub/Views/Planning/PlanningSettingsView.swift index 42d5218..7b67c65 100644 --- a/PadelClub/Views/Planning/PlanningSettingsView.swift +++ b/PadelClub/Views/Planning/PlanningSettingsView.swift @@ -10,36 +10,25 @@ import LeStorage struct PlanningSettingsView: View { @EnvironmentObject var dataStore: DataStore - var tournament: Tournament - @State private var randomCourtDistribution: Bool + @Bindable var tournament: Tournament + @Bindable var matchScheduler: MatchScheduler + @State private var groupStageCourtCount: Int - @State private var upperBracketBreakTime: Bool - @State private var loserBracketBreakTime: Bool - @State private var rotationDifferenceIsImportant: Bool - @State private var loserBracketRotationDifference: Int - @State private var upperBracketRotationDifference: Int - @State private var timeDifferenceLimit: Double - @State private var shouldHandleUpperRoundSlice: Bool @State private var isScheduling: Bool = false @State private var schedulingDone: Bool = false @State private var showOptions: Bool = false - @State private var shouldEndBeforeStartNext: Bool = true init(tournament: Tournament) { self.tournament = tournament + if let matchScheduler = tournament.matchScheduler() { + self.matchScheduler = matchScheduler + } else { + self.matchScheduler = MatchScheduler(tournament: tournament.id) + } self._groupStageCourtCount = State(wrappedValue: tournament.groupStageCourtCount ?? 1) - self._loserBracketRotationDifference = State(wrappedValue: MatchScheduler.shared.loserBracketRotationDifference) - self._upperBracketRotationDifference = State(wrappedValue: MatchScheduler.shared.upperBracketRotationDifference) - self._timeDifferenceLimit = State(wrappedValue: MatchScheduler.shared.timeDifferenceLimit) - self._rotationDifferenceIsImportant = State(wrappedValue: MatchScheduler.shared.rotationDifferenceIsImportant()) - self._randomCourtDistribution = State(wrappedValue: MatchScheduler.shared.randomizeCourts()) - self._upperBracketBreakTime = State(wrappedValue: MatchScheduler.shared.accountUpperBracketBreakTime()) - self._loserBracketBreakTime = State(wrappedValue: MatchScheduler.shared.accountLoserBracketBreakTime()) - self._shouldHandleUpperRoundSlice = State(wrappedValue: MatchScheduler.shared.shouldHandleUpperRoundSlice()) } var body: some View { - @Bindable var tournament = tournament List { SubscriptionInfoView() @@ -80,10 +69,6 @@ struct PlanningSettingsView: View { await _setupSchedule() schedulingDone = true } - - if showOptions { - _optionsView() - } } footer: { Button { showOptions.toggle() @@ -93,23 +78,38 @@ struct PlanningSettingsView: View { } .buttonStyle(.borderless) } + + if showOptions { + _optionsView() + } Section { RowButtonView("Supprimer tous les horaires", role: .destructive) { - let allMatches = tournament.allMatches() - allMatches.forEach({ $0.startDate = nil }) - try? dataStore.matches.addOrUpdate(contentOfs: allMatches) - - let allGroupStages = tournament.groupStages() - allGroupStages.forEach({ $0.startDate = nil }) - try? dataStore.groupStages.addOrUpdate(contentOfs: allGroupStages) - - let allRounds = tournament.allRounds() - allRounds.forEach({ $0.startDate = nil }) - try? dataStore.rounds.addOrUpdate(contentOfs: allRounds) + do { + let allMatches = tournament.allMatches() + allMatches.forEach({ $0.startDate = nil }) + try dataStore.matches.addOrUpdate(contentOfs: allMatches) + + let allGroupStages = tournament.groupStages() + allGroupStages.forEach({ $0.startDate = nil }) + try dataStore.groupStages.addOrUpdate(contentOfs: allGroupStages) + + let allRounds = tournament.allRounds() + allRounds.forEach({ $0.startDate = nil }) + try dataStore.rounds.addOrUpdate(contentOfs: allRounds) + } catch { + Logger.error(error) + } } } } + .onAppear { + do { + try dataStore.matchSchedulers.addOrUpdate(instance: matchScheduler) + } catch { + Logger.error(error) + } + } .overlay(alignment: .bottom) { if schedulingDone { Label("Horaires mis à jour", systemImage: "checkmark.circle.fill") @@ -137,87 +137,70 @@ struct PlanningSettingsView: View { @ViewBuilder private func _optionsView() -> some View { - Toggle(isOn: $randomCourtDistribution) { - Text("Distribuer les terrains au hasard") - } - Toggle(isOn: $shouldHandleUpperRoundSlice) { - Text("Équilibrer les matchs d'une manche sur plusieurs tours") - } - - Toggle(isOn: $shouldEndBeforeStartNext) { - Text("Finir une manche et les matchs de classements avant de continuer") - } - - Toggle(isOn: $upperBracketBreakTime) { - Text("Tableau : tenir compte des pauses") + Section { + Toggle(isOn: $matchScheduler.randomizeCourts) { + Text("Distribuer les terrains au hasard") + } + + Toggle(isOn: $matchScheduler.shouldHandleUpperRoundSlice) { + Text("Équilibrer les matchs d'une manche sur plusieurs tours") + } + + Toggle(isOn: $matchScheduler.shouldEndRoundBeforeStartingNext) { + Text("Finir une manche, classement inclus avant de continuer") + } } - Toggle(isOn: $loserBracketBreakTime) { - Text("Classement : tenir compte des pauses") + Section { + Toggle(isOn: $matchScheduler.accountUpperBracketBreakTime) { + Text("Tenir compte des pauses") + Text("Tableau") + } + + Toggle(isOn: $matchScheduler.accountLoserBracketBreakTime) { + Text("Tenir compte des pauses") + Text("Classement") + } } - Toggle(isOn: $rotationDifferenceIsImportant) { - Text("Forcer un créneau supplémentaire entre 2 phases") + Section { + Toggle(isOn: $matchScheduler.rotationDifferenceIsImportant) { + Text("Forcer un créneau supplémentaire entre 2 phases") + } + + LabeledContent { + StepperView(count: $matchScheduler.upperBracketRotationDifference, minimum: 0, maximum: 2) + } label: { + Text("Tableau") + } + .disabled(matchScheduler.rotationDifferenceIsImportant == false) + + LabeledContent { + StepperView(count: $matchScheduler.loserBracketRotationDifference, minimum: 0, maximum: 2) + } label: { + Text("Classement") + } + .disabled(matchScheduler.rotationDifferenceIsImportant == false) } - LabeledContent { - StepperView(count: $upperBracketRotationDifference, minimum: 0, maximum: 2) - } label: { - Text("Tableau") - } - .disabled(rotationDifferenceIsImportant == false) - - LabeledContent { - StepperView(count: $loserBracketRotationDifference, minimum: 0, maximum: 2) - } label: { - Text("Classement") + Section { + LabeledContent { + StepperView(count: $matchScheduler.timeDifferenceLimit, step: 5) + } label: { + Text("Optimisation des créneaux") + Text("Si libre plus de \(matchScheduler.timeDifferenceLimit) minutes") + } } - .disabled(rotationDifferenceIsImportant == false) - - //timeDifferenceLimit - } private func _setupSchedule() async { - - let matchScheduler = MatchScheduler.shared - - matchScheduler.options.removeAll() - - if shouldEndBeforeStartNext { - matchScheduler.options.insert(.shouldEndRoundBeforeStartingNext) - } - - if randomCourtDistribution { - matchScheduler.options.insert(.randomizeCourts) - } - - if shouldHandleUpperRoundSlice { - matchScheduler.options.insert(.shouldHandleUpperRoundSlice) - } - - if upperBracketBreakTime { - matchScheduler.options.insert(.accountUpperBracketBreakTime) - } - - if loserBracketBreakTime { - matchScheduler.options.insert(.accountLoserBracketBreakTime) - } - - if rotationDifferenceIsImportant { - matchScheduler.options.insert(.rotationDifferenceIsImportant) - } - - matchScheduler.loserBracketRotationDifference = loserBracketRotationDifference - matchScheduler.upperBracketRotationDifference = upperBracketRotationDifference - matchScheduler.timeDifferenceLimit = timeDifferenceLimit - matchScheduler.updateSchedule(tournament: tournament) } private func _save() { do { + try dataStore.matchSchedulers.addOrUpdate(instance: matchScheduler) try dataStore.tournaments.addOrUpdate(instance: tournament) } catch { Logger.error(error) diff --git a/PadelClub/Views/Planning/RoundScheduleEditorView.swift b/PadelClub/Views/Planning/RoundScheduleEditorView.swift index d9149da..cecf708 100644 --- a/PadelClub/Views/Planning/RoundScheduleEditorView.swift +++ b/PadelClub/Views/Planning/RoundScheduleEditorView.swift @@ -54,7 +54,7 @@ struct RoundScheduleEditorView: View { } private func _updateSchedule() async { - MatchScheduler.shared.updateBracketSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) + tournament.matchScheduler()?.updateBracketSchedule(tournament: tournament, fromRoundId: round.id, fromMatchId: nil, startDate: startDate) round.startDate = startDate _save() } diff --git a/PadelClub/Views/Planning/SchedulerView.swift b/PadelClub/Views/Planning/SchedulerView.swift index 8785ecf..9b22844 100644 --- a/PadelClub/Views/Planning/SchedulerView.swift +++ b/PadelClub/Views/Planning/SchedulerView.swift @@ -32,7 +32,7 @@ struct SchedulerView: View { case .scheduleGroupStage: MatchFormatPickingView(matchFormat: $tournament.groupStageMatchFormat) { Task { - MatchScheduler.shared.updateSchedule(tournament: tournament) + tournament.matchScheduler()?.updateSchedule(tournament: tournament) } } .onChange(of: tournament.groupStageMatchFormat) {