Implements separate store for tournaments

multistore
Laurent 1 year ago
parent 87c4b10d97
commit 6f02c3396e
  1. 6
      PadelClub.xcodeproj/project.pbxproj
  2. 3
      PadelClub/Data/Club.swift
  3. 1
      PadelClub/Data/Court.swift
  4. 91
      PadelClub/Data/DataStore.swift
  5. 1
      PadelClub/Data/DateInterval.swift
  6. 1
      PadelClub/Data/Event.swift
  7. 2
      PadelClub/Data/Federal/FederalTournament.swift
  8. 49
      PadelClub/Data/GroupStage.swift
  9. 79
      PadelClub/Data/Match.swift
  10. 11
      PadelClub/Data/MatchScheduler.swift
  11. 1
      PadelClub/Data/MonthData.swift
  12. 14
      PadelClub/Data/PlayerRegistration.swift
  13. 118
      PadelClub/Data/Round.swift
  14. 47
      PadelClub/Data/TeamRegistration.swift
  15. 16
      PadelClub/Data/TeamScore.swift
  16. 94
      PadelClub/Data/Tournament.swift
  17. 56
      PadelClub/Data/TournamentStore.swift
  18. 1
      PadelClub/Data/User.swift
  19. 52
      PadelClub/Utils/Patcher.swift
  20. 2
      PadelClub/Views/Calling/CallMessageCustomizationView.swift
  21. 9
      PadelClub/Views/Calling/CallSettingsView.swift
  22. 9
      PadelClub/Views/Calling/CallView.swift
  23. 2
      PadelClub/Views/Calling/Components/MenuWarningView.swift
  24. 16
      PadelClub/Views/Calling/SendToAllView.swift
  25. 44
      PadelClub/Views/Cashier/CashierSettingsView.swift
  26. 2
      PadelClub/Views/Cashier/Event/EventCreationView.swift
  27. 4
      PadelClub/Views/Club/ClubSearchView.swift
  28. 4
      PadelClub/Views/Club/ClubsView.swift
  29. 2
      PadelClub/Views/Club/CreateClubView.swift
  30. 5
      PadelClub/Views/Components/MatchListView.swift
  31. 9
      PadelClub/Views/GroupStage/Components/GroupStageTeamView.swift
  32. 11
      PadelClub/Views/GroupStage/GroupStageSettingsView.swift
  33. 31
      PadelClub/Views/GroupStage/GroupStageView.swift
  34. 9
      PadelClub/Views/Match/Components/MatchDateView.swift
  35. 13
      PadelClub/Views/Match/MatchDetailView.swift
  36. 4
      PadelClub/Views/Match/MatchRowView.swift
  37. 31
      PadelClub/Views/Match/MatchSetupView.swift
  38. 14
      PadelClub/Views/Navigation/MainView.swift
  39. 53
      PadelClub/Views/Navigation/Ongoing/OngoingView.swift
  40. 2
      PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift
  41. 2
      PadelClub/Views/Navigation/Toolbox/APICallsListView.swift
  42. 8
      PadelClub/Views/Navigation/Toolbox/DebugSettingsView.swift
  43. 62
      PadelClub/Views/Navigation/Toolbox/ToolboxView.swift
  44. 10
      PadelClub/Views/Navigation/Umpire/UmpireView.swift
  45. 10
      PadelClub/Views/Planning/GroupStageScheduleEditorView.swift
  46. 11
      PadelClub/Views/Planning/LoserRoundScheduleEditorView.swift
  47. 9
      PadelClub/Views/Planning/LoserRoundStepScheduleEditorView.swift
  48. 20
      PadelClub/Views/Planning/PlanningSettingsView.swift
  49. 1
      PadelClub/Views/Planning/PlanningView.swift
  50. 8
      PadelClub/Views/Planning/RoundScheduleEditorView.swift
  51. 16
      PadelClub/Views/Planning/SchedulerView.swift
  52. 14
      PadelClub/Views/Player/Components/EditablePlayerView.swift
  53. 9
      PadelClub/Views/Player/Components/PlayerPayView.swift
  54. 10
      PadelClub/Views/Player/Components/PlayerSexPickerView.swift
  55. 10
      PadelClub/Views/Player/PlayerDetailView.swift
  56. 9
      PadelClub/Views/Player/PlayerView.swift
  57. 2
      PadelClub/Views/Round/LoserRoundView.swift
  58. 17
      PadelClub/Views/Round/RoundSettingsView.swift
  59. 11
      PadelClub/Views/Round/RoundView.swift
  60. 11
      PadelClub/Views/Score/EditScoreView.swift
  61. 2
      PadelClub/Views/Shared/SupportButtonView.swift
  62. 11
      PadelClub/Views/Team/EditingTeamView.swift
  63. 10
      PadelClub/Views/Tournament/FileImportView.swift
  64. 2
      PadelClub/Views/Tournament/Screen/BroadcastView.swift
  65. 6
      PadelClub/Views/Tournament/Screen/Components/TournamentClubSettingsView.swift
  66. 11
      PadelClub/Views/Tournament/Screen/Components/TournamentMatchFormatsSettingsView.swift
  67. 11
      PadelClub/Views/Tournament/Screen/Components/UpdateSourceRankDateView.swift
  68. 24
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  69. 13
      PadelClub/Views/Tournament/Screen/TournamentRankView.swift
  70. 4
      PadelClub/Views/Tournament/Shared/TournamentBroadcastRowView.swift
  71. 4
      PadelClub/Views/Tournament/Subscription/Guard.swift
  72. 4
      PadelClub/Views/Tournament/Subscription/Purchase.swift
  73. 0
      PadelClub/Views/Tournament/Subscription/PurchaseListView.swift
  74. 0
      PadelClub/Views/Tournament/Subscription/StoreItem.swift
  75. 2
      PadelClub/Views/Tournament/Subscription/StoreManager.swift
  76. 0
      PadelClub/Views/Tournament/Subscription/SubscriptionInfoView.swift
  77. 2
      PadelClub/Views/Tournament/Subscription/SubscriptionView.swift
  78. 8
      PadelClub/Views/Tournament/TournamentView.swift
  79. 2
      PadelClub/Views/User/ChangePasswordView.swift
  80. 4
      PadelClub/Views/User/LoginView.swift
  81. 2
      PadelClub/Views/User/UserCreationView.swift
  82. 4
      PadelClubTests/ServerDataTests.swift

@ -47,6 +47,7 @@
C4EC6F572BE92CAC000CEAB4 /* local.plist in Resources */ = {isa = PBXBuildFile; fileRef = C4EC6F562BE92CAC000CEAB4 /* local.plist */; };
C4EC6F592BE92D88000CEAB4 /* PListReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EC6F582BE92D88000CEAB4 /* PListReader.swift */; };
C4FC2E272C2AABC90021F3BF /* PasswordField.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FC2E262C2AABC90021F3BF /* PasswordField.swift */; };
C4FC2E2B2C2C0E4D0021F3BF /* TournamentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4FC2E2A2C2C0E4D0021F3BF /* TournamentStore.swift */; };
FF025AD82BD0C10F00A86CF8 /* TeamHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF025AD72BD0C10F00A86CF8 /* TeamHeaderView.swift */; };
FF025ADB2BD0C2D000A86CF8 /* MatchTeamDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF025ADA2BD0C2D000A86CF8 /* MatchTeamDetailView.swift */; };
FF025ADD2BD0C94300A86CF8 /* FooterButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF025ADC2BD0C94300A86CF8 /* FooterButtonView.swift */; };
@ -335,6 +336,7 @@
C4EC6F562BE92CAC000CEAB4 /* local.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = local.plist; sourceTree = "<group>"; };
C4EC6F582BE92D88000CEAB4 /* PListReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PListReader.swift; sourceTree = "<group>"; };
C4FC2E262C2AABC90021F3BF /* PasswordField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordField.swift; sourceTree = "<group>"; };
C4FC2E2A2C2C0E4D0021F3BF /* TournamentStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentStore.swift; sourceTree = "<group>"; };
FF025AD72BD0C10F00A86CF8 /* TeamHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeamHeaderView.swift; sourceTree = "<group>"; };
FF025ADA2BD0C2D000A86CF8 /* MatchTeamDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatchTeamDetailView.swift; sourceTree = "<group>"; };
FF025ADC2BD0C94300A86CF8 /* FooterButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterButtonView.swift; sourceTree = "<group>"; };
@ -707,6 +709,7 @@
children = (
C411C9CC2BF21DAF003017AD /* README.md */,
C4A47D5D2B6D38EC00ADC637 /* DataStore.swift */,
C4FC2E2A2C2C0E4D0021F3BF /* TournamentStore.swift */,
C4A47DAC2B85FCCD00ADC637 /* User.swift */,
C4A47D592B6D383C00ADC637 /* Tournament.swift */,
FF967CE72BAEC70100A9A3BD /* GroupStage.swift */,
@ -745,7 +748,6 @@
FF11627B2BCF937F000C4809 /* Cashier */,
FFBF41802BF73EA2001B24CB /* Event */,
FF3F74F72B919F96004CFE0E /* Tournament */,
C4A47D882B7BBB5000ADC637 /* Subscription */,
C4A47D852B7BA33F00ADC637 /* User */,
FF6EC8FC2B9478C800EA7F5A /* Shared */,
C4A47DA02B7D0BD800ADC637 /* Components */,
@ -956,6 +958,7 @@
FF1F4B702BF9EFE9000B4573 /* TournamentInscriptionView.swift */,
FF1F4B6C2BF9E60B000B4573 /* TournamentBuildView.swift */,
FF967CF52BAED51600A9A3BD /* TournamentRunningView.swift */,
C4A47D882B7BBB5000ADC637 /* Subscription */,
FF089EBE2BB0B14600F0AEC7 /* FileImportView.swift */,
FF3F74F92B91A018004CFE0E /* Screen */,
FF3F74F82B919FB2004CFE0E /* Shared */,
@ -1595,6 +1598,7 @@
FF1162872BD004AD000C4809 /* EditingTeamView.swift in Sources */,
FF6EC9062B947A1000EA7F5A /* NetworkManagerError.swift in Sources */,
C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */,
C4FC2E2B2C2C0E4D0021F3BF /* TournamentStore.swift in Sources */,
FF5647132C0B6F390081F995 /* LoserRoundSettingsView.swift in Sources */,
FF3795662B9399AA004EA093 /* Persistence.swift in Sources */,
FF1DF49B2BD8D23900822FA0 /* BarButtonView.swift in Sources */,

@ -14,6 +14,7 @@ class Club : ModelObject, Storable, Hashable {
static func resourceName() -> String { return "clubs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [.get] }
static func filterByStoreIdentifier() -> Bool { return false }
static func == (lhs: Club, rhs: Club) -> Bool {
lhs.id == rhs.id
@ -235,7 +236,7 @@ extension Club {
if clubs.isEmpty == false {
return clubs.first!
} else {
return Club(creator: Store.main.userId, name: name, code: code, city: city, zipCode: zipCode)
return Club(creator: StoreCenter.main.userId, name: name, code: code, city: city, zipCode: zipCode)
}
}

@ -13,6 +13,7 @@ import LeStorage
class Court : ModelObject, Storable, Hashable {
static func resourceName() -> String { return "courts" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
static func == (lhs: Court, rhs: Court) -> Bool {
lhs.id == rhs.id

@ -16,12 +16,12 @@ class DataStore: ObservableObject {
@Published var user: User = User.placeHolder() {
didSet {
let loggedUser = (user.username.count > 0)
Store.main.collectionsCanSynchronize = loggedUser
StoreCenter.main.collectionsCanSynchronize = loggedUser
if loggedUser {
if self.user.id != self.userStorage.item()?.id {
self.userStorage.setItemNoSync(self.user)
if Store.main.collectionsCanSynchronize {
if StoreCenter.main.collectionsCanSynchronize {
Store.main.loadCollectionFromServer()
self._fixMissingClubCreatorIfNecessary(self.clubs)
self._fixMissingEventCreatorIfNecessary(self.events)
@ -37,15 +37,15 @@ class DataStore: ObservableObject {
fileprivate(set) var clubs: StoredCollection<Club>
fileprivate(set) var courts: StoredCollection<Court>
fileprivate(set) var events: StoredCollection<Event>
fileprivate(set) var groupStages: StoredCollection<GroupStage>
fileprivate(set) var matches: StoredCollection<Match>
fileprivate(set) var teamRegistrations: StoredCollection<TeamRegistration>
fileprivate(set) var playerRegistrations: StoredCollection<PlayerRegistration>
fileprivate(set) var rounds: StoredCollection<Round>
fileprivate(set) var teamScores: StoredCollection<TeamScore>
// fileprivate(set) var groupStages: StoredCollection<GroupStage>
// fileprivate(set) var matches: StoredCollection<Match>
// fileprivate(set) var teamRegistrations: StoredCollection<TeamRegistration>
// fileprivate(set) var playerRegistrations: StoredCollection<PlayerRegistration>
// fileprivate(set) var rounds: StoredCollection<Round>
// fileprivate(set) var teamScores: StoredCollection<TeamScore>
fileprivate(set) var monthData: StoredCollection<MonthData>
fileprivate(set) var dateIntervals: StoredCollection<DateInterval>
fileprivate(set) var matchSchedulers: StoredCollection<MatchScheduler>
// fileprivate(set) var matchSchedulers: StoredCollection<MatchScheduler>
fileprivate var userStorage: StoredSingleton<User>
@ -59,21 +59,21 @@ class DataStore: ObservableObject {
init() {
let store = Store.main
let serverURL: String = URLs.api.rawValue
store.blackListUserName("apple-test")
StoreCenter.main.blackListUserName("apple-test")
#if DEBUG
if let server = PListReader.readString(plist: "local", key: "server") {
store.synchronizationApiURL = server
StoreCenter.main.synchronizationApiURL = server
} else {
store.synchronizationApiURL = serverURL
StoreCenter.main.synchronizationApiURL = serverURL
}
#else
store.synchronizationApiURL = serverURL
#endif
store.logsFailedAPICalls()
StoreCenter.main.logsFailedAPICalls()
var synchronized : Bool = true
var synchronized: Bool = true
_ = Guard.main // init
@ -83,22 +83,22 @@ class DataStore: ObservableObject {
}
#endif
Logger.log("Sync URL: \(store.synchronizationApiURL ?? "none"), sync: \(synchronized) ")
Logger.log("Sync URL: \(StoreCenter.main.synchronizationApiURL ?? "none"), sync: \(synchronized) ")
let indexed : Bool = true
let indexed: Bool = true
self.clubs = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.courts = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.tournaments = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.events = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.groupStages = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.teamScores = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.teamRegistrations = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.playerRegistrations = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.rounds = store.registerCollection(synchronized: synchronized, indexed: indexed)
self.matches = store.registerCollection(synchronized: synchronized, indexed: indexed)
// self.groupStages = store.registerCollection(synchronized: synchronized, indexed: indexed)
// self.teamScores = store.registerCollection(synchronized: synchronized, indexed: indexed)
// self.teamRegistrations = store.registerCollection(synchronized: synchronized, indexed: indexed)
// self.playerRegistrations = store.registerCollection(synchronized: synchronized, indexed: indexed)
// self.rounds = store.registerCollection(synchronized: synchronized, indexed: indexed)
// 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.matchSchedulers = store.registerCollection(synchronized: false, indexed: indexed)
self.userStorage = store.registerObject(synchronized: synchronized)
@ -139,7 +139,7 @@ class DataStore: ObservableObject {
fileprivate func _fixMissingClubCreatorIfNecessary(_ clubsCollection: StoredCollection<Club>) {
for club in clubsCollection {
if let userId = Store.main.userId, club.creator == nil {
if let userId = StoreCenter.main.userId, club.creator == nil {
club.creator = userId
self.userStorage.item()?.addClub(club)
clubsCollection.writeChangeAndInsertOnServer(instance: club)
@ -149,7 +149,7 @@ class DataStore: ObservableObject {
fileprivate func _fixMissingEventCreatorIfNecessary(_ eventsCollection: StoredCollection<Event>) {
for event in eventsCollection {
if let userId = Store.main.userId, event.creator == nil {
if let userId = StoreCenter.main.userId, event.creator == nil {
event.creator = userId
do {
try event.insertOnServer()
@ -167,7 +167,7 @@ class DataStore: ObservableObject {
func disconnect() {
Task {
if await Store.main.hasPendingAPICalls() {
if await StoreCenter.main.hasPendingAPICalls() {
// todo qu'est ce qu'on fait des API Call ?
}
}
@ -175,21 +175,26 @@ class DataStore: ObservableObject {
self.user = self._temporaryLocalUser.item ?? User.placeHolder()
self.user.clubs.removeAll()
Store.main.disconnect()
Store.main.collectionsCanSynchronize = false
StoreCenter.main.disconnect()
StoreCenter.main.collectionsCanSynchronize = false
for tournament in self.tournaments {
StoreCenter.main.destroyStore(identifier: tournament.id)
}
self.tournaments.reset()
self.clubs.reset()
self.courts.reset()
self.events.reset()
self.groupStages.reset()
self.matches.reset()
self.teamRegistrations.reset()
self.playerRegistrations.reset()
self.rounds.reset()
self.teamScores.reset()
// self.groupStages.reset()
// self.matches.reset()
// self.teamRegistrations.reset()
// self.playerRegistrations.reset()
// self.rounds.reset()
// self.teamScores.reset()
self.dateIntervals.reset()
self.matchSchedulers.reset()
// self.matchSchedulers.reset()
self.userStorage.reset()
Guard.main.disconnect()
@ -256,4 +261,20 @@ class DataStore: ObservableObject {
}
// MARK: - Convenience
func runningMatches() -> [Match] {
// let tournaments: [Tournament] = self.tournaments // foutu
let lastTournaments = self.tournaments.sorted(by: \Tournament.startDate).prefix(10)
var runningMatches: [Match] = []
for tournament in lastTournaments {
let matches = tournament.tournamentStore.matches.filter { match in
match.confirmed && match.startDate != nil && match.endDate == nil && match.courtIndex != nil }
runningMatches.append(contentsOf: matches)
}
return runningMatches
}
}

@ -13,6 +13,7 @@ import LeStorage
class DateInterval: ModelObject, Storable {
static func resourceName() -> String { return "date-intervals" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
var id: String = Store.randomId()
var event: String

@ -14,6 +14,7 @@ class Event: ModelObject, Storable {
static func resourceName() -> String { return "events" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
var id: String = Store.randomId()
var creator: String?

@ -20,7 +20,7 @@ struct FederalTournament: Identifiable, Codable {
let club = DataStore.shared.user.clubsObjects().first(where: { $0.code == codeClub })
var event = DataStore.shared.events.first(where: { $0.tenupId == id.string })
if event == nil {
event = Event(creator: Store.main.userId, club: club?.id, name: libelle, tenupId: id.string)
event = Event(creator: StoreCenter.main.userId, club: club?.id, name: libelle, tenupId: id.string)
do {
try DataStore.shared.events.addOrUpdate(instance: event!)
} catch {

@ -14,6 +14,7 @@ import SwiftUI
class GroupStage: ModelObject, Storable {
static func resourceName() -> String { "group-stages" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
var id: String = Store.randomId()
var tournament: String
@ -41,10 +42,15 @@ class GroupStage: ModelObject, Storable {
self.name = name
}
var tournamentStore: TournamentStore {
return TournamentStore.instance(tournamentId: self.tournament)
}
// MARK: - Computed dependencies
func _matches() -> [Match] {
Store.main.filter { $0.groupStage == self.id }
return self.tournamentStore.matches.filter { $0.groupStage == self.id }
// Store.main.filter { $0.groupStage == self.id }
}
func tournamentObject() -> Tournament? {
@ -82,21 +88,31 @@ class GroupStage: ModelObject, Storable {
return _matches.anySatisfy { $0.hasEnded() == false } == false
}
fileprivate func _createMatch(index: Int) -> Match {
let match: Match = Match(groupStage: self.id,
index: index,
matchFormat: self.matchFormat,
name: self.localizedMatchUpLabel(for: index))
match.store = self.store
return match
}
func buildMatches() {
_removeMatches()
var _matches = [Match]()
var _teamScores = [TeamScore]()
var matches = [Match]()
var teamScores = [TeamScore]()
for i in 0..<_numberOfMatchesToBuild() {
let newMatch = Match(groupStage: id, index: i, matchFormat: matchFormat, name: localizedMatchUpLabel(for: i))
_teamScores.append(contentsOf: newMatch.createTeamScores())
_matches.append(newMatch)
let newMatch = self._createMatch(index: i)
// let newMatch = Match(groupStage: self.id, index: i, matchFormat: self.matchFormat, name: localizedMatchUpLabel(for: i))
teamScores.append(contentsOf: newMatch.createTeamScores())
matches.append(newMatch)
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: _matches)
try DataStore.shared.teamScores.addOrUpdate(contentOfs: _teamScores)
try self.tournamentStore.matches.addOrUpdate(contentOfs: matches)
try self.tournamentStore.teamScores.addOrUpdate(contentOfs: teamScores)
} catch {
Logger.error(error)
}
@ -124,7 +140,7 @@ class GroupStage: ModelObject, Storable {
team.bracketPosition = nil
}
}
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teams)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -286,7 +302,7 @@ class GroupStage: ModelObject, Storable {
private func _removeMatches() {
do {
try DataStore.shared.matches.delete(contentOfs: _matches())
try self.tournamentStore.matches.delete(contentOfs: _matches())
} catch {
Logger.error(error)
}
@ -315,7 +331,8 @@ class GroupStage: ModelObject, Storable {
}
func unsortedTeams() -> [TeamRegistration] {
Store.main.filter { $0.groupStage == self.id && $0.groupStagePosition != nil }
return self.tournamentStore.teamRegistrations.filter { $0.groupStage == self.id && $0.groupStagePosition != nil }
// Store.main.filter { $0.groupStage == self.id && $0.groupStagePosition != nil }
}
func teams(_ sortedByScore: Bool = false, scores: [TeamGroupStageScore]? = nil) -> [TeamRegistration] {
@ -357,14 +374,14 @@ class GroupStage: ModelObject, Storable {
match.matchFormat = matchFormat
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: playedMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: playedMatches)
} catch {
Logger.error(error)
}
}
override func deleteDependencies() throws {
DataStore.shared.matches.deleteDependencies(self._matches())
self.tournamentStore.matches.deleteDependencies(self._matches())
}
func encode(to encoder: Encoder) throws {
@ -394,10 +411,10 @@ class GroupStage: ModelObject, Storable {
}
}
func insertOnServer() throws {
try DataStore.shared.groupStages.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.groupStages.writeChangeAndInsertOnServer(instance: self)
for match in self._matches() {
try match.insertOnServer()
match.insertOnServer()
}
}

@ -12,7 +12,8 @@ import LeStorage
class Match: ModelObject, Storable {
static func resourceName() -> String { "matches" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
static func setServerTitle(upperRound: Round, matchIndex: Int) -> String {
if upperRound.index == 0 { return upperRound.roundTitle() }
return upperRound.roundTitle() + " #" + (matchIndex + 1).formatted()
@ -38,7 +39,7 @@ class Match: ModelObject, Storable {
private(set) var courtIndex: Int?
var confirmed: Bool = false
internal init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, name: String? = nil, disabled: Bool = false, courtIndex: Int? = nil, confirmed: Bool = false) {
init(round: String? = nil, groupStage: String? = nil, startDate: Date? = nil, endDate: Date? = nil, index: Int, matchFormat: MatchFormat? = nil, servingTeamId: String? = nil, winningTeamId: String? = nil, losingTeamId: String? = nil, name: String? = nil, disabled: Bool = false, courtIndex: Int? = nil, confirmed: Bool = false) {
self.round = round
self.groupStage = groupStage
self.startDate = startDate
@ -57,16 +58,27 @@ class Match: ModelObject, Storable {
// self.order = order
}
var tournamentStore: TournamentStore {
if let store = self.store as? TournamentStore {
return store
}
fatalError("missing store for \(String(describing: type(of: self)))")
}
// MARK: - Computed dependencies
var teamScores: [TeamScore] {
return Store.main.filter { $0.match == self.id }
return self.tournamentStore.teamScores.filter { $0.match == self.id }
// return Store.main.filter { $0.match == self.id }
}
// MARK: -
override func deleteDependencies() throws {
DataStore.shared.teamScores.deleteDependencies(self.teamScores)
guard let tournament = self.currentTournament() else {
return
}
tournament.tournamentStore.teamScores.deleteDependencies(self.teamScores)
}
func indexInRound(in matches: [Match]? = nil) -> Int {
@ -140,7 +152,7 @@ class Match: ModelObject, Storable {
func winner() -> TeamRegistration? {
guard let winningTeamId else { return nil }
return Store.main.findById(winningTeamId)
return self.tournamentStore.teamRegistrations.findById(winningTeamId)
}
func localizedStartDate() -> String {
@ -169,7 +181,7 @@ class Match: ModelObject, Storable {
followingMatch()?.cleanScheduleAndSave(nil)
_loserMatch()?.cleanScheduleAndSave(nil)
do {
try DataStore.shared.matches.addOrUpdate(instance: self)
try self.tournamentStore.matches.addOrUpdate(instance: self)
} catch {
Logger.error(error)
}
@ -186,7 +198,7 @@ class Match: ModelObject, Storable {
func resetScores() {
teamScores.forEach({ $0.score = nil })
do {
try DataStore.shared.teamScores.addOrUpdate(contentOfs: teamScores)
try self.tournamentStore.teamScores.addOrUpdate(contentOfs: teamScores)
} catch {
Logger.error(error)
}
@ -196,14 +208,14 @@ class Match: ModelObject, Storable {
resetMatch()
let previousScores = teamScores.filter({ $0.luckyLoser != nil })
do {
try DataStore.shared.teamScores.delete(contentOfs: previousScores)
try self.tournamentStore.teamScores.delete(contentOfs: previousScores)
} catch {
Logger.error(error)
}
if let existingTeamScore = teamScore(ofTeam: team) {
do {
try DataStore.shared.teamScores.delete(instance: existingTeamScore)
try self.tournamentStore.teamScores.delete(instance: existingTeamScore)
} catch {
Logger.error(error)
}
@ -212,7 +224,7 @@ class Match: ModelObject, Storable {
let teamScoreWalkout = TeamScore(match: id, team: team)
teamScoreWalkout.walkOut = 1
do {
try DataStore.shared.teamScores.addOrUpdate(instance: teamScoreWalkout)
try self.tournamentStore.teamScores.addOrUpdate(instance: teamScoreWalkout)
} catch {
Logger.error(error)
}
@ -230,14 +242,14 @@ class Match: ModelObject, Storable {
resetMatch()
let previousScores = teamScores.filter({ $0.luckyLoser != nil })
do {
try DataStore.shared.teamScores.delete(contentOfs: previousScores)
try self.tournamentStore.teamScores.delete(contentOfs: previousScores)
} catch {
Logger.error(error)
}
if let existingTeamScore = teamScore(ofTeam: team) {
do {
try DataStore.shared.teamScores.delete(instance: existingTeamScore)
try self.tournamentStore.teamScores.delete(instance: existingTeamScore)
} catch {
Logger.error(error)
}
@ -248,7 +260,7 @@ class Match: ModelObject, Storable {
let teamScoreLuckyLoser = TeamScore(match: id, team: team)
teamScoreLuckyLoser.luckyLoser = position
do {
try DataStore.shared.teamScores.addOrUpdate(instance: teamScoreLuckyLoser)
try self.tournamentStore.teamScores.addOrUpdate(instance: teamScoreLuckyLoser)
} catch {
Logger.error(error)
}
@ -285,13 +297,18 @@ class Match: ModelObject, Storable {
let bottomMatchIndex = (nextIndex + 1) * 2
let isTopMatch = topMatchIndex + 1 == index
let lookingForIndex = isTopMatch ? topMatchIndex : bottomMatchIndex
return Store.main.filter(isIncluded: { $0.round == round && $0.index == lookingForIndex }).first
return self.tournamentStore.matches.first(where: { $0.round == round && $0.index == lookingForIndex })
// return Store.main.filter(isIncluded: { $0.round == round && $0.index == lookingForIndex }).first
}
private func _forwardMatch(inRound round: Round) -> Match? {
guard let roundObjectNextRound = round.nextRound() else { return nil }
let nextIndex = (index - 1) / 2
return Store.main.filter(isIncluded: { $0.round == roundObjectNextRound.id && $0.index == nextIndex }).first
return self.tournamentStore.matches.first(where: { $0.round == roundObjectNextRound.id && $0.index == nextIndex })
// return Store.main.filter(isIncluded: { $0.round == roundObjectNextRound.id && $0.index == nextIndex }).first
}
func _toggleForwardMatchDisableState(_ state: Bool) {
@ -335,7 +352,7 @@ class Match: ModelObject, Storable {
disabled = state
//byeState = false
do {
try DataStore.shared.matches.addOrUpdate(instance: self)
try self.tournamentStore.matches.addOrUpdate(instance: self)
} catch {
Logger.error(error)
}
@ -350,7 +367,8 @@ class Match: ModelObject, Storable {
}
func next() -> Match? {
return Store.main.filter(isIncluded: { $0.round == round && $0.index > index }).sorted(by: \.index).first
let matches: [Match] = self.tournamentStore.matches.filter { $0.round == round && $0.index > index }
return matches.sorted(by: \.index).first
}
func followingMatch() -> Match? {
@ -359,7 +377,8 @@ class Match: ModelObject, Storable {
}
func getFollowingMatch(fromNextRoundId nextRoundId: String) -> Match? {
return Store.main.filter(isIncluded: { $0.round == nextRoundId && $0.index == (index - 1) / 2 }).first
return self.tournamentStore.matches.first(where: { $0.round == nextRoundId && $0.index == (index - 1) / 2 })
// return Store.main.filter(isIncluded: { $0.round == nextRoundId && $0.index == (index - 1) / 2 }).first
}
func getDuration() -> Int {
@ -386,7 +405,7 @@ class Match: ModelObject, Storable {
func topPreviousRoundMatch() -> Match? {
guard let roundObject else { return nil }
let matches: [Match] = Store.main.filter { match in
let matches: [Match] = self.tournamentStore.matches.filter { match in
match.index == topPreviousRoundMatchIndex() && match.round != nil && match.round == roundObject.previousRound()?.id
}
return matches.sorted(by: \.index).first
@ -394,7 +413,7 @@ class Match: ModelObject, Storable {
func bottomPreviousRoundMatch() -> Match? {
guard let roundObject else { return nil }
let matches: [Match] = Store.main.filter { match in
let matches: [Match] = self.tournamentStore.matches.filter { match in
match.index == bottomPreviousRoundMatchIndex() && match.round != nil && match.round == roundObject.previousRound()?.id
}
return matches.sorted(by: \.index).first
@ -428,7 +447,7 @@ class Match: ModelObject, Storable {
func previousMatches() -> [Match] {
guard let roundObject else { return [] }
return Store.main.filter { match in
return self.tournamentStore.matches.filter { match in
(match.index == topPreviousRoundMatchIndex() || match.index == bottomPreviousRoundMatchIndex())
&& match.round == roundObject.previousRound()?.id
}.sorted(by: \.index)
@ -449,7 +468,7 @@ class Match: ModelObject, Storable {
let teamScoreWinning = teamScore(teamPosition.otherTeam) ?? TeamScore(match: id, team: team(teamPosition.otherTeam))
teamScoreWinning.walkOut = nil
do {
try DataStore.shared.teamScores.addOrUpdate(contentOfs: [teamScoreWalkout, teamScoreWinning])
try self.tournamentStore.teamScores.addOrUpdate(contentOfs: [teamScoreWalkout, teamScoreWinning])
} catch {
Logger.error(error)
}
@ -486,7 +505,7 @@ class Match: ModelObject, Storable {
let teamScoreTwo = teamScore(.two) ?? TeamScore(match: id, team: team(.two))
teamScoreTwo.score = matchDescriptor.teamTwoScores.joined(separator: ",")
do {
try DataStore.shared.teamScores.addOrUpdate(contentOfs: [teamScoreOne, teamScoreTwo])
try self.tournamentStore.teamScores.addOrUpdate(contentOfs: [teamScoreOne, teamScoreTwo])
} catch {
Logger.error(error)
}
@ -503,7 +522,7 @@ class Match: ModelObject, Storable {
let teamScores = teamScores.filter({ ids.contains($0.id) == false })
if teamScores.isEmpty == false {
do {
try DataStore.shared.teamScores.delete(contentOfs: teamScores)
try self.tournamentStore.teamScores.delete(contentOfs: teamScores)
} catch {
Logger.error(error)
}
@ -529,7 +548,7 @@ class Match: ModelObject, Storable {
func updateTeamScores() {
let teams = getOrCreateTeamScores()
do {
try DataStore.shared.teamScores.addOrUpdate(contentOfs: teams)
try self.tournamentStore.teamScores.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -660,7 +679,7 @@ class Match: ModelObject, Storable {
}
func scores() -> [TeamScore] {
return Store.main.filter(isIncluded: { $0.match == id })
return self.tournamentStore.teamScores.filter { $0.match == id }
}
func teams() -> [TeamRegistration] {
@ -773,12 +792,12 @@ class Match: ModelObject, Storable {
var roundObject: Round? {
guard let round else { return nil }
return Store.main.findById(round)
return self.tournamentStore.rounds.findById(round)
}
var groupStageObject: GroupStage? {
guard let groupStage else { return nil }
return Store.main.findById(groupStage)
return self.tournamentStore.groupStages.findById(groupStage)
}
var isLoserBracket: Bool {
@ -877,8 +896,8 @@ class Match: ModelObject, Storable {
try container.encode(confirmed, forKey: ._confirmed)
}
func insertOnServer() throws {
try DataStore.shared.matches.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.matches.writeChangeAndInsertOnServer(instance: self)
for teamScore in self.teamScores {
try teamScore.insertOnServer()
}

@ -14,6 +14,7 @@ class MatchScheduler : ModelObject, Storable {
static func resourceName() -> String { return "match-scheduler" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
private(set) var id: String = Store.randomId()
var tournament: String
@ -79,6 +80,10 @@ class MatchScheduler : ModelObject, Storable {
return tournamentObject()?.additionalEstimationDuration ?? 0
}
var tournamentStore: TournamentStore {
return TournamentStore.instance(tournamentId: self.tournament)
}
func tournamentObject() -> Tournament? {
return Store.main.findById(tournament)
}
@ -132,7 +137,7 @@ class MatchScheduler : ModelObject, Storable {
groupStages.filter({ $0.startDate == nil || times.contains($0.startDate!) == false }).chunked(into: computedGroupStageChunkCount).forEach { groups in
groups.forEach({ $0.startDate = lastDate })
do {
try DataStore.shared.groupStages.addOrUpdate(contentOfs: groups)
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: groups)
} catch {
Logger.error(error)
}
@ -153,7 +158,7 @@ class MatchScheduler : ModelObject, Storable {
}
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: matches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: matches)
} catch {
Logger.error(error)
}
@ -649,7 +654,7 @@ class MatchScheduler : ModelObject, Storable {
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: allMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
} catch {
Logger.error(error)
}

@ -14,6 +14,7 @@ class MonthData : ModelObject, Storable {
static func resourceName() -> String { return "month-data" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
private(set) var id: String = Store.randomId()
private(set) var monthKey: String

@ -12,6 +12,7 @@ import LeStorage
class PlayerRegistration: ModelObject, Storable {
static func resourceName() -> String { "player-registrations" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
var id: String = Store.randomId()
var teamRegistration: String?
@ -95,6 +96,13 @@ class PlayerRegistration: ModelObject, Storable {
self.sex = PlayerSexType(rawValue: sex)
}
}
var tournamentStore: TournamentStore {
if let store = self.store as? TournamentStore {
return store
}
fatalError("missing store for \(String(describing: type(of: self)))")
}
var computedAge: Int? {
if let birthdate {
@ -140,7 +148,7 @@ class PlayerRegistration: ModelObject, Storable {
func team() -> TeamRegistration? {
guard let teamRegistration else { return nil }
return Store.main.findById(teamRegistration)
return self.tournamentStore.teamRegistrations.findById(teamRegistration)
}
func hasPaid() -> Bool {
@ -472,8 +480,8 @@ class PlayerRegistration: ModelObject, Storable {
}
}
func insertOnServer() throws {
try DataStore.shared.playerRegistrations.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.playerRegistrations.writeChangeAndInsertOnServer(instance: self)
}
}

@ -13,6 +13,7 @@ import SwiftUI
class Round: ModelObject, Storable {
static func resourceName() -> String { "rounds" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
var id: String = Store.randomId()
var tournament: String
@ -31,16 +32,22 @@ class Round: ModelObject, Storable {
// MARK: - Computed dependencies
var tournamentStore: TournamentStore {
return TournamentStore.instance(tournamentId: self.tournament)
}
func tournamentObject() -> Tournament? {
return Store.main.findById(tournament)
}
func _matches() -> [Match] {
return Store.main.filter { $0.round == self.id }
return self.tournamentStore.matches.filter { $0.round == self.id }
// return Store.main.filter { $0.round == self.id }
}
func getDisabledMatches() -> [Match] {
return Store.main.filter { $0.round == self.id && $0.disabled == true }
return self.tournamentStore.matches.filter { $0.round == self.id && $0.disabled == true }
// return Store.main.filter { $0.round == self.id && $0.disabled == true }
}
// MARK: -
@ -54,7 +61,6 @@ class Round: ModelObject, Storable {
}
}
func hasStarted() -> Bool {
return playedMatches().anySatisfy({ $0.hasStarted() })
}
@ -74,9 +80,14 @@ class Round: ModelObject, Storable {
func previousMatches(ofMatch match: Match) -> [Match] {
guard let previousRound = previousRound() else { return [] }
return Store.main.filter {
return self.tournamentStore.filter {
($0.index == match.topPreviousRoundMatchIndex() || $0.index == match.bottomPreviousRoundMatchIndex()) && $0.round == previousRound.id
}
// return Store.main.filter {
// ($0.index == match.topPreviousRoundMatchIndex() || $0.index == match.bottomPreviousRoundMatchIndex()) && $0.round == previousRound.id
// }
}
func precedentMatches(ofMatch match: Match) -> [Match] {
@ -102,35 +113,49 @@ class Round: ModelObject, Storable {
}
func seed(_ team: TeamPosition, inMatchIndex matchIndex: Int) -> TeamRegistration? {
return Store.main.filter(isIncluded: {
return self.tournamentStore.teamRegistrations.first(where: {
$0.tournament == tournament
&& $0.bracketPosition != nil
&& ($0.bracketPosition! / 2) == matchIndex
&& ($0.bracketPosition! % 2) == team.rawValue
}).first
})
// return Store.main.filter(isIncluded: {
// $0.tournament == tournament
// && $0.bracketPosition != nil
// && ($0.bracketPosition! / 2) == matchIndex
// && ($0.bracketPosition! % 2) == team.rawValue
// }).first
}
func seeds(inMatchIndex matchIndex: Int) -> [TeamRegistration] {
return Store.main.filter(isIncluded: {
return self.tournamentStore.teamRegistrations.filter {
$0.tournament == tournament
&& $0.bracketPosition != nil
&& ($0.bracketPosition! / 2) == matchIndex
})
}
// return Store.main.filter(isIncluded: {
// $0.tournament == tournament
// && $0.bracketPosition != nil
// && ($0.bracketPosition! / 2) == matchIndex
// })
}
func seeds() -> [TeamRegistration] {
let initialMatchIndex = RoundRule.matchIndex(fromRoundIndex: index)
let numberOfMatches = RoundRule.numberOfMatches(forRoundIndex: index)
return Store.main.filter(isIncluded: {
return self.tournamentStore.teamRegistrations.filter {
$0.tournament == tournament
&& $0.bracketPosition != nil
&& ($0.bracketPosition! / 2) >= initialMatchIndex
&& ($0.bracketPosition! / 2) < initialMatchIndex + numberOfMatches
})
}
}
func losers() -> [TeamRegistration] {
return _matches().compactMap { $0.losingTeamId }.compactMap { Store.main.findById($0) }
let teamIds: [String] = self._matches().compactMap { $0.losingTeamId }
return teamIds.compactMap { self.tournamentStore.teamRegistrations.findById($0) }
}
func teams() -> [TeamRegistration] {
@ -147,10 +172,10 @@ class Round: ModelObject, Storable {
if let luckyLoser = match.teamScores.first(where: { $0.luckyLoser == match.index * 2 }) {
return luckyLoser.team
} else if let parent = upperBracketTopMatch(ofMatchIndex: match.index)?.losingTeamId {
return Store.main.findById(parent)
return self.tournamentStore.teamRegistrations.findById(parent)
} else if let previousMatch = topPreviousRoundMatch(ofMatch: match) {
if let teamId = previousMatch.winningTeamId {
return Store.main.findById(teamId)
return self.tournamentStore.teamRegistrations.findById(teamId)
} else if previousMatch.disabled {
return previousMatch.teams().first
}
@ -159,10 +184,10 @@ class Round: ModelObject, Storable {
if let luckyLoser = match.teamScores.first(where: { $0.luckyLoser == match.index * 2 + 1 }) {
return luckyLoser.team
} else if let parent = upperBracketBottomMatch(ofMatchIndex: match.index)?.losingTeamId {
return Store.main.findById(parent)
return self.tournamentStore.teamRegistrations.findById(parent)
} else if let previousMatch = bottomPreviousRoundMatch(ofMatch: match) {
if let teamId = previousMatch.winningTeamId {
return Store.main.findById(teamId)
return self.tournamentStore.teamRegistrations.findById(teamId)
} else if previousMatch.disabled {
return previousMatch.teams().first
}
@ -190,29 +215,39 @@ class Round: ModelObject, Storable {
func topPreviousRoundMatch(ofMatch match: Match) -> Match? {
guard let previousRound = previousRound() else { return nil }
let matches: [Match] = Store.main.filter {
let matches: [Match] = self.tournamentStore.matches.filter {
$0.index == match.topPreviousRoundMatchIndex() && $0.round == previousRound.id
}
// let matches: [Match] = Store.main.filter {
// $0.index == match.topPreviousRoundMatchIndex() && $0.round == previousRound.id
// }
return matches.sorted(by: \.index).first
}
func bottomPreviousRoundMatch(ofMatch match: Match) -> Match? {
guard let previousRound = previousRound() else { return nil }
let matches: [Match] = Store.main.filter {
let matches: [Match] = self.tournamentStore.matches.filter {
$0.index == match.bottomPreviousRoundMatchIndex() && $0.round == previousRound.id
}
return matches.sorted(by: \.index).first
}
func getMatch(atMatchIndexInRound matchIndexInRound: Int) -> Match? {
Store.main.filter(isIncluded: {
return self.tournamentStore.matches.first(where: {
let index = RoundRule.matchIndexWithinRound(fromMatchIndex: $0.index)
return $0.round == id && index == matchIndexInRound
}).first
})
// Store.main.filter(isIncluded: {
// let index = RoundRule.matchIndexWithinRound(fromMatchIndex: $0.index)
// return $0.round == id && index == matchIndexInRound
// }).first
}
func enabledMatches() -> [Match] {
return Store.main.filter { $0.round == self.id && $0.disabled == false }
return self.tournamentStore.matches.filter { $0.round == self.id && $0.disabled == false }
// return Store.main.filter { $0.round == self.id && $0.disabled == false }
}
func displayableMatches() -> [Match] {
@ -234,11 +269,12 @@ class Round: ModelObject, Storable {
}
func previousRound() -> Round? {
return Store.main.filter(isIncluded: { $0.tournament == tournament && $0.parent == parent && $0.index == index + 1 }).first
return self.tournamentStore.rounds.first(where: { $0.tournament == tournament && $0.parent == parent && $0.index == index + 1 })
// return Store.main.filter(isIncluded: { $0.tournament == tournament && $0.parent == parent && $0.index == index + 1 }).first
}
func nextRound() -> Round? {
return Store.main.filter(isIncluded: { $0.tournament == tournament && $0.parent == parent && $0.index == index - 1 }).first
return self.tournamentStore.rounds.first(where: { $0.tournament == tournament && $0.parent == parent && $0.index == index - 1 })
}
func loserRounds(forRoundIndex roundIndex: Int) -> [Round] {
@ -302,7 +338,7 @@ class Round: ModelObject, Storable {
// }
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: _matches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: _matches)
} catch {
Logger.error(error)
}
@ -352,11 +388,18 @@ class Round: ModelObject, Storable {
func correspondingLoserRoundTitle(_ displayStyle: DisplayStyle = .wide) -> String {
let initialMatchIndexFromRoundIndex = RoundRule.matchIndex(fromRoundIndex: index)
let seedsAfterThisRound : [TeamRegistration] = Store.main.filter(isIncluded: {
let seedsAfterThisRound: [TeamRegistration] = self.tournamentStore.teamRegistrations.filter {
$0.tournament == tournament
&& $0.bracketPosition != nil
&& ($0.bracketPosition! / 2) < initialMatchIndexFromRoundIndex
})
}
// let seedsAfterThisRound : [TeamRegistration] = Store.main.filter(isIncluded: {
// $0.tournament == tournament
// && $0.bracketPosition != nil
// && ($0.bracketPosition! / 2) < initialMatchIndexFromRoundIndex
// })
let playedMatches = playedMatches()
let seedInterval = SeedInterval(first: playedMatches.count + seedsAfterThisRound.count + 1, last: playedMatches.count * 2 + seedsAfterThisRound.count)
return seedInterval.localizedLabel(displayStyle)
@ -370,11 +413,11 @@ class Round: ModelObject, Storable {
if parent == nil {
let numberOfMatches = RoundRule.numberOfMatches(forRoundIndex: index + 1)
let initialMatchIndexFromRoundIndex = RoundRule.matchIndex(fromRoundIndex: index)
let seedsAfterThisRound : [TeamRegistration] = Store.main.filter(isIncluded: {
let seedsAfterThisRound : [TeamRegistration] = self.tournamentStore.teamRegistrations.filter {
$0.tournament == tournament
&& $0.bracketPosition != nil
&& ($0.bracketPosition! / 2) < initialMatchIndexFromRoundIndex
})
}
let playedMatches = playedMatches()
let reduce = numberOfMatches / 2 - (playedMatches.count + seedsAfterThisRound.count)
return SeedInterval(first: 1, last: numberOfMatches, reduce: reduce)
@ -419,7 +462,8 @@ class Round: ModelObject, Storable {
}
func loserRounds() -> [Round] {
return Store.main.filter(isIncluded: { $0.parent == id }).sorted(by: \.index).reversed()
let rounds: [Round] = self.tournamentStore.rounds.filter { $0.parent == id }
return rounds.sorted(by: \.index).reversed()
}
func loserRoundsAndChildren() -> [Round] {
@ -449,7 +493,7 @@ class Round: ModelObject, Storable {
}
do {
try DataStore.shared.rounds.addOrUpdate(contentOfs: rounds)
try self.tournamentStore.rounds.addOrUpdate(contentOfs: rounds)
} catch {
Logger.error(error)
}
@ -462,7 +506,7 @@ class Round: ModelObject, Storable {
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: matches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: matches)
} catch {
Logger.error(error)
}
@ -474,7 +518,7 @@ class Round: ModelObject, Storable {
var parentRound: Round? {
guard let parent = parent else { return nil }
return Store.main.findById(parent)
return self.tournamentStore.rounds.findById(parent)
}
func updateMatchFormat(_ updatedMatchFormat: MatchFormat, checkIfPossible: Bool, andLoserBracket: Bool) {
@ -499,15 +543,15 @@ class Round: ModelObject, Storable {
match.matchFormat = updatedMatchFormat
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: playedMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: playedMatches)
} catch {
Logger.error(error)
}
}
override func deleteDependencies() throws {
DataStore.shared.matches.deleteDependencies(self._matches())
DataStore.shared.rounds.deleteDependencies(self.loserRoundsAndChildren())
self.tournamentStore.matches.deleteDependencies(self._matches())
self.tournamentStore.rounds.deleteDependencies(self.loserRoundsAndChildren())
}
enum CodingKeys: String, CodingKey {
@ -545,10 +589,10 @@ class Round: ModelObject, Storable {
}
}
func insertOnServer() throws {
try DataStore.shared.rounds.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.rounds.writeChangeAndInsertOnServer(instance: self)
for match in self._matches() {
try match.insertOnServer()
match.insertOnServer()
}
}

@ -12,6 +12,7 @@ import LeStorage
class TeamRegistration: ModelObject, Storable {
static func resourceName() -> String { "team-registrations" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
var id: String = Store.randomId()
var tournament: String
@ -57,24 +58,29 @@ class TeamRegistration: ModelObject, Storable {
self.qualified = qualified
}
var tournamentStore: TournamentStore {
return TournamentStore.instance(tournamentId: self.tournament)
}
// MARK: - Computed dependencies
func unsortedPlayers() -> [PlayerRegistration] {
Store.main.filter { $0.teamRegistration == self.id }
return self.tournamentStore.playerRegistrations.filter { $0.teamRegistration == self.id }
// Store.main.filter { $0.teamRegistration == self.id }
}
// MARK: -
override func deleteDependencies() throws {
DataStore.shared.playerRegistrations.deleteDependencies(self.unsortedPlayers())
DataStore.shared.teamScores.deleteDependencies(self.teamScores())
self.tournamentStore.playerRegistrations.deleteDependencies(self.unsortedPlayers())
self.tournamentStore.teamScores.deleteDependencies(self.teamScores())
}
func hasArrived() {
let unsortedPlayers = unsortedPlayers()
unsortedPlayers.forEach({ $0.hasArrived = true })
do {
try DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: unsortedPlayers)
try self.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: unsortedPlayers)
} catch {
Logger.error(error)
}
@ -138,19 +144,23 @@ class TeamRegistration: ModelObject, Storable {
}
func teamScores() -> [TeamScore] {
return Store.main.filter(isIncluded: { $0.teamRegistration == id })
return self.tournamentStore.teamScores.filter { $0.teamRegistration == id }
// return Store.main.filter(isIncluded: { $0.teamRegistration == id })
}
func wins() -> [Match] {
return Store.main.filter(isIncluded: { $0.winningTeamId == id })
return self.tournamentStore.matches.filter { $0.winningTeamId == id }
// return Store.main.filter(isIncluded: { $0.winningTeamId == id })
}
func loses() -> [Match] {
return Store.main.filter(isIncluded: { $0.losingTeamId == id })
return self.tournamentStore.matches.filter { $0.losingTeamId == id }
// return Store.main.filter(isIncluded: { $0.losingTeamId == id })
}
func matches() -> [Match] {
return Store.main.filter(isIncluded: { $0.losingTeamId == id || $0.winningTeamId == id })
return self.tournamentStore.matches.filter { $0.losingTeamId == id || $0.winningTeamId == id }
// return Store.main.filter(isIncluded: { $0.losingTeamId == id || $0.winningTeamId == id })
}
var tournamentCategory: TournamentCategory {
@ -273,7 +283,7 @@ class TeamRegistration: ModelObject, Storable {
let previousPlayers = Set(unsortedPlayers())
let playersToRemove = previousPlayers.subtracting(players)
do {
try DataStore.shared.playerRegistrations.delete(contentOfs: playersToRemove)
try self.tournamentStore.playerRegistrations.delete(contentOfs: playersToRemove)
} catch {
Logger.error(error)
}
@ -323,7 +333,10 @@ class TeamRegistration: ModelObject, Storable {
typealias AreInIncreasingOrder = (PlayerRegistration, PlayerRegistration) -> Bool
func players() -> [PlayerRegistration] {
Store.main.filter { $0.teamRegistration == self.id }.sorted { (lhs, rhs) in
let playerRegistration = self.tournamentStore.playerRegistrations.filter { $0.teamRegistration == self.id }
return playerRegistration.sorted { (lhs, rhs) in
let predicates: [AreInIncreasingOrder] = [
{ $0.sex?.rawValue ?? 0 < $1.sex?.rawValue ?? 0 },
{ $0.rank ?? 0 < $1.rank ?? 0 },
@ -371,19 +384,21 @@ class TeamRegistration: ModelObject, Storable {
func groupStageObject() -> GroupStage? {
guard let groupStage else { return nil }
return Store.main.findById(groupStage)
return self.tournamentStore.groupStages.findById(groupStage)
}
func initialRound() -> Round? {
guard let bracketPosition else { return nil }
let roundIndex = RoundRule.roundIndex(fromMatchIndex: bracketPosition / 2)
return Store.main.filter(isIncluded: { $0.tournament == tournament && $0.index == roundIndex }).first
return self.tournamentStore.rounds.first(where: { $0.index == roundIndex })
// return Store.main.filter(isIncluded: { $0.tournament == tournament && $0.index == roundIndex }).first
}
func initialMatch() -> Match? {
guard let bracketPosition else { return nil }
guard let initialRoundObject = initialRound() else { return nil }
return Store.main.filter(isIncluded: { $0.round == initialRoundObject.id && $0.index == bracketPosition / 2 }).first
return self.tournamentStore.matches.first(where: { $0.round == initialRoundObject.id && $0.index == bracketPosition / 2 })
// return Store.main.filter(isIncluded: { $0.round == initialRoundObject.id && $0.index == bracketPosition / 2 }).first
}
@ -513,10 +528,10 @@ class TeamRegistration: ModelObject, Storable {
}
}
func insertOnServer() throws {
try DataStore.shared.teamRegistrations.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.teamRegistrations.writeChangeAndInsertOnServer(instance: self)
for playerRegistration in self.unsortedPlayers() {
try playerRegistration.insertOnServer()
playerRegistration.insertOnServer()
}
}

@ -13,6 +13,7 @@ class TeamScore: ModelObject, Storable {
static func resourceName() -> String { "team-scores" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return true }
var id: String = Store.randomId()
var match: String
@ -42,17 +43,24 @@ class TeamScore: ModelObject, Storable {
self.luckyLoser = nil
}
var tournamentStore: TournamentStore {
if let store = self.store as? TournamentStore {
return store
}
fatalError("missing store for \(String(describing: type(of: self)))")
}
// MARK: - Computed dependencies
func matchObject() -> Match? {
return DataStore.shared.matches.findById(self.match)
return self.tournamentStore.matches.findById(self.match)
}
var team: TeamRegistration? {
guard let teamRegistration else {
return nil
}
return DataStore.shared.teamRegistrations.findById(teamRegistration)
return self.tournamentStore.teamRegistrations.findById(teamRegistration)
}
// MARK: -
@ -104,8 +112,8 @@ class TeamScore: ModelObject, Storable {
}
}
func insertOnServer() throws {
try DataStore.shared.teamScores.writeChangeAndInsertOnServer(instance: self)
func insertOnServer() {
self.tournamentStore.teamScores.writeChangeAndInsertOnServer(instance: self)
}
}

@ -12,6 +12,7 @@ import LeStorage
class Tournament : ModelObject, Storable {
static func resourceName() -> String { "tournaments" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
var id: String = Store.randomId()
var event: String?
@ -334,26 +335,35 @@ class Tournament : ModelObject, Storable {
}
}
var tournamentStore: TournamentStore {
return TournamentStore.instance(tournamentId: self.id)
}
override func deleteDependencies() throws {
DataStore.shared.teamRegistrations.deleteDependencies(self.unsortedTeams())
DataStore.shared.groupStages.deleteDependencies(self.groupStages())
DataStore.shared.rounds.deleteDependencies(self.rounds())
DataStore.shared.matchSchedulers.deleteDependencies(self._matchSchedulers())
let store = self.tournamentStore
store.teamRegistrations.deleteDependencies(self.unsortedTeams())
store.groupStages.deleteDependencies(self.groupStages())
store.rounds.deleteDependencies(self.rounds())
store.matchSchedulers.deleteDependencies(self._matchSchedulers())
}
// MARK: - Computed Dependencies
func unsortedTeams() -> [TeamRegistration] {
return Store.main.filter { $0.tournament == self.id }
return Array(self.tournamentStore.teamRegistrations)
}
func groupStages() -> [GroupStage] {
let groupStages: [GroupStage] = DataStore.shared.groupStages.filter { $0.tournament == self.id }
let groupStages: [GroupStage] = self.tournamentStore.groupStages.filter { $0.tournament == self.id }
return groupStages.sorted(by: \.index)
}
func allGroupStages() -> [GroupStage] {
return Array(self.tournamentStore.groupStages)
}
func allRounds() -> [Round] {
return Store.main.filter { $0.tournament == self.id }
return Array(self.tournamentStore.rounds)
}
// MARK: -
@ -476,7 +486,8 @@ class Tournament : ModelObject, Storable {
}
func courtUsed() -> [Int] {
let runningMatches : [Match] = Store.main.filter(isIncluded: { $0.isRunning() }).filter({ $0.tournamentId() == self.id })
let runningMatches: [Match] = self.tournamentStore.matches.filter { $0.isRunning() }
// let runningMatches : [Match] = Store.main.filter(isIncluded: { $0.isRunning() }).filter({ $0.tournamentId() == self.id })
return Set(runningMatches.compactMap { $0.courtIndex }).sorted()
}
@ -569,7 +580,8 @@ class Tournament : ModelObject, Storable {
}
func getRound(atRoundIndex roundIndex: Int) -> Round? {
return Store.main.filter(isIncluded: { $0.tournament == id && $0.index == roundIndex }).first
return self.tournamentStore.rounds.first(where: { $0.index == roundIndex })
// return Store.main.filter(isIncluded: { $0.tournament == id && $0.index == roundIndex }).first
}
func availableSeedSpot(inRoundIndex roundIndex: Int) -> [Match] {
@ -746,18 +758,19 @@ class Tournament : ModelObject, Storable {
}
func allMatches() -> [Match] {
let unsortedGroupStages : [GroupStage] = Store.main.filter { $0.tournament == self.id }
let matches: [Match] = unsortedGroupStages.flatMap { $0._matches() } + allRoundMatches()
let unsortedGroupStages: [GroupStage] = Store.main.filter { $0.tournament == self.id }
let matches: [Match] = self.allGroupStages().flatMap { $0._matches() } + allRoundMatches()
return matches.filter({ $0.disabled == false })
}
func _allMatchesIncludingDisabled() -> [Match] {
let unsortedGroupStages : [GroupStage] = Store.main.filter { $0.tournament == self.id }
return unsortedGroupStages.flatMap { $0._matches() } + allRounds().flatMap { $0._matches() }
return self.allGroupStages().flatMap { $0._matches() } + allRounds().flatMap { $0._matches() }
}
func rounds() -> [Round] {
Store.main.filter { $0.tournament == self.id && $0.parent == nil }.sorted(by: \.index).reversed()
let rounds: [Round] = self.tournamentStore.rounds.filter { $0.parent == nil }
return rounds.sorted(by: \.index).reversed()
// Store.main.filter { $0.tournament == self.id && $0.parent == nil }.sorted(by: \.index).reversed()
}
func sortedTeams() -> [TeamRegistration] {
@ -842,11 +855,13 @@ class Tournament : ModelObject, Storable {
}
func unsortedTeamsWithoutWO() -> [TeamRegistration] {
return Store.main.filter { $0.tournament == self.id && $0.walkOut == false }
return self.tournamentStore.teamRegistrations.filter { $0.walkOut == false }
// return Store.main.filter { $0.tournament == self.id && $0.walkOut == false }
}
func walkoutTeams() -> [TeamRegistration] {
return Store.main.filter { $0.tournament == self.id && $0.walkOut == true }
return self.tournamentStore.teamRegistrations.filter { $0.walkOut == true }
// return Store.main.filter { $0.tournament == self.id && $0.walkOut == true }
}
func duplicates(in players: [PlayerRegistration]) -> [PlayerRegistration] {
@ -971,12 +986,12 @@ class Tournament : ModelObject, Storable {
}
do {
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teamsToImport)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teamsToImport)
} catch {
Logger.error(error)
}
do {
try DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: teams.flatMap { $0.players })
try self.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: teams.flatMap { $0.players })
} catch {
Logger.error(error)
}
@ -1015,7 +1030,8 @@ class Tournament : ModelObject, Storable {
func groupStagesMatches() -> [Match] {
let groupStageIds = groupStages().map { $0.id }
return Store.main.filter(isIncluded: { $0.groupStage != nil && groupStageIds.contains($0.groupStage!) })
return self.tournamentStore.matches.filter { $0.groupStage != nil && groupStageIds.contains($0.groupStage!) }
// return Store.main.filter(isIncluded: { $0.groupStage != nil && groupStageIds.contains($0.groupStage!) })
}
func availableToStart(_ allMatches: [Match], in runningMatches: [Match]) async -> [Match] {
@ -1148,7 +1164,7 @@ class Tournament : ModelObject, Storable {
team.lockedWeight = team.weight
}
do {
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teams)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -1161,13 +1177,13 @@ class Tournament : ModelObject, Storable {
players.forEach { $0.setComputedRank(in: self) }
team.setWeight(from: players, inTournamentCategory: tournamentCategory)
do {
try DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: players)
try self.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
}
do {
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teams)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -1418,7 +1434,7 @@ class Tournament : ModelObject, Storable {
}
do {
try DataStore.shared.groupStages.addOrUpdate(contentOfs: _groupStages)
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: _groupStages)
} catch {
Logger.error(error)
}
@ -1440,7 +1456,7 @@ class Tournament : ModelObject, Storable {
}
do {
try DataStore.shared.rounds.addOrUpdate(contentOfs: rounds)
try self.tournamentStore.rounds.addOrUpdate(contentOfs: rounds)
} catch {
Logger.error(error)
}
@ -1457,7 +1473,7 @@ class Tournament : ModelObject, Storable {
})
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: matches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: matches)
} catch {
Logger.error(error)
}
@ -1471,8 +1487,9 @@ class Tournament : ModelObject, Storable {
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
if let round: Round = self.getRound(atRoundIndex: roundIndex) {
return self.tournamentStore.matches.first(where: { $0.round == round.id && $0.index == matchIndex })
// return Store.main.filter(isIncluded: { $0.round == round.id && $0.index == matchIndex }).first
}
return nil
}
@ -1489,13 +1506,13 @@ class Tournament : ModelObject, Storable {
func deleteStructure() {
do {
try DataStore.shared.rounds.delete(contentOfs: rounds())
try self.tournamentStore.rounds.delete(contentOfs: rounds())
} catch {
Logger.error(error)
}
unsortedTeams().forEach({ $0.bracketPosition = nil })
do {
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
} catch {
Logger.error(error)
}
@ -1503,7 +1520,7 @@ class Tournament : ModelObject, Storable {
func deleteGroupStages() {
do {
try DataStore.shared.groupStages.delete(contentOfs: groupStages())
try self.tournamentStore.groupStages.delete(contentOfs: groupStages())
} catch {
Logger.error(error)
}
@ -1513,7 +1530,7 @@ class Tournament : ModelObject, Storable {
$0.groupStage = nil
$0.groupStagePosition = nil
})
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
} catch {
Logger.error(error)
}
@ -1564,7 +1581,7 @@ class Tournament : ModelObject, Storable {
}
do {
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams())
} catch {
Logger.error(error)
}
@ -1725,7 +1742,7 @@ class Tournament : ModelObject, Storable {
private let _currentSelectionSorting : [MySortDescriptor<TeamRegistration>] = [.keyPath(\.weight), .keyPath(\.registrationDate!)]
private func _matchSchedulers() -> [MatchScheduler] {
return DataStore.shared.matchSchedulers.filter { $0.tournament == self.id }
return self.tournamentStore.matchSchedulers.filter { $0.tournament == self.id }
// DataStore.shared.matchSchedulers.filter(isIncluded: { $0.tournament == self.id })
}
@ -1736,7 +1753,8 @@ class Tournament : ModelObject, Storable {
func currentMonthData() -> MonthData? {
guard let rankSourceDate else { return nil }
let dateString = URL.importDateFormatter.string(from: rankSourceDate)
return Store.main.filter(isIncluded: { $0.monthKey == dateString }).first
return DataStore.shared.monthData.first(where: { $0.monthKey == dateString })
// return Store.main.filter(isIncluded: { $0.monthKey == dateString }).first
}
var maleUnrankedValue: Int? {
@ -1756,9 +1774,11 @@ class Tournament : ModelObject, Storable {
}
func tournamentWinner() -> TeamRegistration? {
let rounds: [Round] = Store.main.filter(isIncluded: { $0.index == 0 && $0.tournament == id && $0.parent == nil })
let finals: Round? = self.tournamentStore.rounds.first(where: { $0.index == 0 && $0.parent == nil })
// let rounds: [Round] = Store.main.filter(isIncluded: { $0.index == 0 && $0.tournament == id && $0.parent == nil })
// let final: Round? = .first
return rounds.first?.playedMatches().first?.winner()
return finals?.playedMatches().first?.winner()
}
func getGroupStageChunkValue() -> Int {
@ -1796,7 +1816,7 @@ class Tournament : ModelObject, Storable {
func insertOnServer() throws {
try DataStore.shared.tournaments.writeChangeAndInsertOnServer(instance: self)
DataStore.shared.tournaments.writeChangeAndInsertOnServer(instance: self)
for teamRegistration in self.unsortedTeams() {
try teamRegistration.insertOnServer()

@ -0,0 +1,56 @@
//
// TournamentStore.swift
// PadelClub
//
// Created by Laurent Morvillier on 26/06/2024.
//
import Foundation
import LeStorage
import SwiftUI
class TournamentStore: Store, ObservableObject {
static func instance(tournamentId: String) -> TournamentStore {
return StoreCenter.main.store(identifier: tournamentId, parameter: "tournament")
}
fileprivate(set) var groupStages: StoredCollection<GroupStage> = StoredCollection.placeholder()
fileprivate(set) var matches: StoredCollection<Match> = StoredCollection.placeholder()
fileprivate(set) var teamRegistrations: StoredCollection<TeamRegistration> = StoredCollection.placeholder()
fileprivate(set) var playerRegistrations: StoredCollection<PlayerRegistration> = StoredCollection.placeholder()
fileprivate(set) var rounds: StoredCollection<Round> = StoredCollection.placeholder()
fileprivate(set) var teamScores: StoredCollection<TeamScore> = StoredCollection.placeholder()
fileprivate(set) var matchSchedulers: StoredCollection<MatchScheduler> = StoredCollection.placeholder()
// fileprivate(set) var loading: Bool = true
convenience init(tournament: Tournament) {
self.init(identifier: tournament.id, parameter: "tournament")
}
required init(identifier: String, parameter: String) {
super.init(identifier: identifier, parameter: parameter)
var synchronized: Bool = true
let indexed: Bool = true
#if DEBUG
if let sync = PListReader.readBool(plist: "local", key: "synchronized") {
synchronized = sync
}
#endif
self.groupStages = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.teamRegistrations = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.playerRegistrations = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.rounds = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.matches = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.teamScores = self.registerCollection(synchronized: synchronized, indexed: indexed)
self.matchSchedulers = self.registerCollection(synchronized: false, indexed: indexed)
}
}

@ -19,6 +19,7 @@ class User: ModelObject, UserBase, Storable {
static func resourceName() -> String { "users" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [.post] }
static func filterByStoreIdentifier() -> Bool { return false }
// func deleteDependencies() throws { }

@ -40,16 +40,16 @@ class Patcher {
}
fileprivate static func _patchAlexisLeDu() {
guard Store.main.userId == "94f45ed2-8938-4c32-a4b6-e4525073dd33" else { return }
guard StoreCenter.main.userId == "94f45ed2-8938-4c32-a4b6-e4525073dd33" else { return }
Logger.log(">>> Start patch...")
let clubs = DataStore.shared.clubs
clubs.resetApiCalls()
StoreCenter.main.resetApiCalls(collection: clubs)
// clubs.resetApiCalls()
for club in clubs.filter({ $0.creator == "d5060b89-e979-4c19-bf78-e459a6ed5318"}) {
club.creator = Store.main.userId
club.creator = StoreCenter.main.userId
clubs.writeChangeAndInsertOnServer(instance: club)
}
@ -57,25 +57,28 @@ class Patcher {
fileprivate static func _importDataFromDev() {
guard let userId = Store.main.userId else {
guard let userId = StoreCenter.main.userId else {
return
}
return // TODO review
let services = Services(url: "https://xlr.alwaysdata.net/roads/")
if services.hasToken() {
Task {
let clubs: [Club] = try await services.get()
let events: [Event] = try await services.get()
let tournaments: [Tournament] = try await services.get()
let rounds: [Round] = try await services.get()
let groupStages: [GroupStage] = try await services.get()
let matches: [Match] = try await services.get()
let teamRegistrations: [TeamRegistration] = try await services.get()
let teamScores: [TeamScore] = try await services.get()
let playerRegistrations: [PlayerRegistration] = try await services.get()
let courts: [Court] = try await services.get()
let dateIntervals: [DateInterval] = try await services.get()
let clubs: [Club] = try await Store.main.getItems()
let events: [Event] = try await Store.main.getItems()
let tournaments: [Tournament] = try await Store.main.getItems()
// let rounds: [Round] = try await services.get()
// let groupStages: [GroupStage] = try await services.get()
// let matches: [Match] = try await services.get()
// let teamRegistrations: [TeamRegistration] = try await services.get()
// let teamScores: [TeamScore] = try await services.get()
// let playerRegistrations: [PlayerRegistration] = try await services.get()
let courts: [Court] = try await Store.main.getItems()
let dateIntervals: [DateInterval] = try await Store.main.getItems()
// for club in clubs {
// club.creator = userId
@ -93,14 +96,19 @@ class Patcher {
// try DataStore.shared.clubs.addOrUpdate(contentOfs: clubs)
try DataStore.shared.events.addOrUpdate(contentOfs: events)
try DataStore.shared.tournaments.addOrUpdate(contentOfs: tournaments)
try DataStore.shared.rounds.addOrUpdate(contentOfs: rounds)
try DataStore.shared.groupStages.addOrUpdate(contentOfs: groupStages)
try DataStore.shared.matches.addOrUpdate(contentOfs: matches)
try DataStore.shared.teamRegistrations.addOrUpdate(contentOfs: teamRegistrations)
try DataStore.shared.teamScores.addOrUpdate(contentOfs: teamScores)
try DataStore.shared.playerRegistrations.addOrUpdate(contentOfs: playerRegistrations)
try DataStore.shared.courts.addOrUpdate(contentOfs: courts)
try DataStore.shared.dateIntervals.addOrUpdate(contentOfs: dateIntervals)
// for tournament in DataStore.shared.tournaments {
// let store = tournament.tournamentStore
// try store.rounds.addOrUpdate(contentOfs: rounds)
// try store.groupStages.addOrUpdate(contentOfs: groupStages)
// try store.matches.addOrUpdate(contentOfs: matches)
// try store.teamRegistrations.addOrUpdate(contentOfs: teamRegistrations)
// try store.teamScores.addOrUpdate(contentOfs: teamScores)
// try store.playerRegistrations.addOrUpdate(contentOfs: playerRegistrations)
// }
}
}

@ -206,7 +206,7 @@ struct CallMessageCustomizationView: View {
@ViewBuilder
private func _clubNameView() -> some View {
if let eventClub = tournament.eventObject()?.clubObject() {
let hasBeenCreated: Bool = eventClub.hasBeenCreated(by: Store.main.userId)
let hasBeenCreated: Bool = eventClub.hasBeenCreated(by: StoreCenter.main.userId)
Section {
TextField("Nom du club", text: $customClubName, axis: .vertical)
.lineLimit(2)

@ -10,10 +10,15 @@ import LeStorage
struct CallSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@State private var showSendToAllView: Bool = false
@State private var addLink: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
List {
@ -59,7 +64,7 @@ struct CallSettingsView: View {
team.callDate = nil
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -73,7 +78,7 @@ struct CallSettingsView: View {
team.callDate = team.expectedSummonDate()
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}

@ -49,6 +49,7 @@ struct CallView: View {
}
@EnvironmentObject var dataStore: DataStore
@EnvironmentObject var networkMonitor: NetworkMonitor
@Environment(Tournament.self) var tournament: Tournament
@ -66,6 +67,10 @@ struct CallView: View {
@State var summonParamByMessage: Bool = false
@State var summonParamReSummon: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var messageSentFailed: Binding<Bool> {
Binding {
sentError != nil
@ -82,7 +87,7 @@ struct CallView: View {
team.callDate = callDate
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -229,7 +234,7 @@ struct CallView: View {
}
fileprivate func _verifyUser(_ handler: () -> ()) {
if Store.main.userId != nil {
if StoreCenter.main.userId != nil {
handler()
} else {
self.showUserCreationView = true

@ -142,7 +142,7 @@ struct MenuWarningView: View {
}
fileprivate func _verifyUser(_ handler: () -> ()) {
if Store.main.userId != nil {
if StoreCenter.main.userId != nil {
handler()
} else {
self.showUserCreationView = true

@ -9,8 +9,10 @@ import SwiftUI
import LeStorage
struct SendToAllView: View {
@Environment(\.dismiss) var dismiss
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var networkMonitor: NetworkMonitor
@ -28,6 +30,10 @@ struct SendToAllView: View {
@State var summonParamByMessage: Bool = false
@State var summonParamReSummon: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var messageSentFailed: Binding<Bool> {
Binding {
sentError != nil
@ -181,13 +187,13 @@ struct SendToAllView: View {
}
func _roundTeams() -> [TeamRegistration] {
let rounds : [Round] = contactRecipients.compactMap { Store.main.findById($0) }
return rounds.flatMap({ $0.teams() })
let rounds: [Round] = contactRecipients.compactMap { self.tournamentStore.rounds.findById($0) }
return rounds.flatMap { $0.teams() }
}
func _groupStagesTeams() -> [TeamRegistration] {
let groupStages : [GroupStage] = contactRecipients.compactMap { Store.main.findById($0) }
return groupStages.flatMap({ $0.teams() })
let groupStages : [GroupStage] = contactRecipients.compactMap { self.tournamentStore.groupStages.findById($0) }
return groupStages.flatMap { $0.teams() }
}
func _totalString() -> String {
@ -229,7 +235,7 @@ struct SendToAllView: View {
}
fileprivate func _verifyUser(_ handler: () -> ()) {
if Store.main.userId != nil {
if StoreCenter.main.userId != nil {
handler()
} else {
self.showUserCreationView = true

@ -9,7 +9,9 @@ import SwiftUI
import LeStorage
struct CashierSettingsView: View {
@EnvironmentObject var dataStore: DataStore
var tournaments: [Tournament]
init(tournaments: [Tournament]) {
@ -24,17 +26,21 @@ struct CashierSettingsView: View {
List {
Section {
RowButtonView("Tout le monde a réglé", role: .destructive) {
let players = tournaments.flatMap({ $0.selectedPlayers() })
players.forEach { player in
if player.hasPaid() == false {
player.paymentType = .gift
for tournament in self.tournaments {
let players = tournament.selectedPlayers() // tournaments.flatMap({ $0.selectedPlayers() })
players.forEach { player in
if player.hasPaid() == false {
player.paymentType = .gift
}
}
do {
try tournament.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
}
} footer: {
Text("Passe tous les joueurs qui n'ont pas réglé en offert")
@ -42,14 +48,18 @@ struct CashierSettingsView: View {
Section {
RowButtonView("Personne n'a réglé", role: .destructive) {
let players = tournaments.flatMap({ $0.selectedPlayers() })
players.forEach { player in
player.paymentType = nil
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
for tournament in self.tournaments {
let store = tournament.tournamentStore
let players = tournament.selectedPlayers()
players.forEach { player in
player.paymentType = nil
}
do {
try store.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
}
}
} footer: {

@ -129,7 +129,7 @@ struct EventCreationView: View {
}
private func _validate() {
let event = Event(creator: Store.main.userId, name: eventName)
let event = Event(creator: StoreCenter.main.userId, name: eventName)
do {
try dataStore.events.addOrUpdate(instance: event)

@ -303,7 +303,7 @@ struct ClubSearchView: View {
}
private func _importClub(clubToEdit: Club, clubMarker: ClubMarker) {
if clubToEdit.hasBeenCreated(by: Store.main.userId) {
if clubToEdit.hasBeenCreated(by: StoreCenter.main.userId) {
if clubToEdit.name.isEmpty {
clubToEdit.name = clubMarker.nom.capitalized
clubToEdit.acronym = clubToEdit.automaticShortName().capitalized
@ -314,7 +314,7 @@ struct ClubSearchView: View {
clubToEdit.city = clubMarker.ville
}
if displayContext == .addition && clubToEdit.hasBeenCreated(by: Store.main.userId) {
if displayContext == .addition && clubToEdit.hasBeenCreated(by: StoreCenter.main.userId) {
do {
try dataStore.clubs.addOrUpdate(instance: clubToEdit)
} catch {

@ -62,7 +62,7 @@ struct ClubsView: View {
.buttonStyle(.plain)
} else {
NavigationLink {
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: Store.main.userId) ? .edition : .lockedForEditing)
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: StoreCenter.main.userId) ? .edition : .lockedForEditing)
} label: {
ClubRowView(club: club)
}
@ -88,7 +88,7 @@ struct ClubsView: View {
.buttonStyle(.plain)
} else {
NavigationLink {
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: Store.main.userId) ? .edition : .lockedForEditing)
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: StoreCenter.main.userId) ? .edition : .lockedForEditing)
} label: {
ClubRowView(club: club)
}

@ -52,7 +52,7 @@ struct CreateClubView: View {
let newClub = Club.findOrCreate(name: club.name, code: club.code, city: club.city, zipCode: club.zipCode)
//update existing club if rights ok / freshly created club with data input from user
if newClub.hasBeenCreated(by: Store.main.userId) {
if newClub.hasBeenCreated(by: StoreCenter.main.userId) {
newClub.update(fromClub: club)
do {
try dataStore.clubs.addOrUpdate(instance: newClub)

@ -8,7 +8,10 @@
import SwiftUI
struct MatchListView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament
let section: String
let matches: [Match]?
var matchViewStyle: MatchViewStyle = .standardStyle
@ -31,7 +34,7 @@ struct MatchListView: View {
DisclosureGroup(isExpanded: $isExpanded) {
if let matches {
ForEach(matches) { match in
MatchRowView(match: match, matchViewStyle: matchViewStyle)
MatchRowView(match: match, tournament: self.tournament, matchViewStyle: matchViewStyle)
.listRowInsets(EdgeInsets(top: 0, leading: -2, bottom: 0, trailing: 8))
}
}

@ -9,11 +9,18 @@ import SwiftUI
import LeStorage
struct GroupStageTeamView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@Environment(\.dismiss) private var dismiss
let groupStage: GroupStage
var team: TeamRegistration
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
List {
Section {
@ -85,7 +92,7 @@ struct GroupStageTeamView: View {
private func _save() {
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}

@ -10,9 +10,14 @@ import LeStorage
struct GroupStageSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@State private var generationDone: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
List {
@ -68,7 +73,7 @@ struct GroupStageSettingsView: View {
}
}
do {
try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
try self.tournament.tournamentStore.groupStages.addOrUpdate(contentOfs: groupStages)
} catch {
Logger.error(error)
}
@ -82,7 +87,7 @@ struct GroupStageSettingsView: View {
groupStage.name = nil
}
do {
try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
try self.tournament.tournamentStore.groupStages.addOrUpdate(contentOfs: groupStages)
} catch {
Logger.error(error)
}

@ -9,7 +9,9 @@ import SwiftUI
import LeStorage
struct GroupStageView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) private var tournament
@Bindable var groupStage: GroupStage
@State private var confirmGroupStageStart: Bool = false
@ -27,6 +29,10 @@ struct GroupStageView: View {
self.playedMatches = groupStage.playedMatches()
}
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
List {
Section {
@ -92,12 +98,19 @@ struct GroupStageView: View {
}
struct GroupStageScoreView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) private var tournament
let groupStage: GroupStage
let sortByScore: Bool
let scores: [GroupStage.TeamGroupStageScore]?
let teams: [TeamRegistration]
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(groupStage: GroupStage, sortByScore: Bool) {
self.groupStage = groupStage
self.sortByScore = sortByScore
@ -114,6 +127,7 @@ struct GroupStageView: View {
if let team = _teamAt(atIndex: index), let groupStagePosition = team.groupStagePosition {
NavigationLink {
GroupStageTeamView(groupStage: groupStage, team: team)
.environment(self.tournament)
} label: {
VStack(alignment: .leading, spacing: 4.0) {
HStack(spacing: 6.0) {
@ -177,7 +191,7 @@ struct GroupStageView: View {
team.groupStagePosition = index
groupStage._matches().forEach({ $0.updateTeamScores() })
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
@ -214,7 +228,7 @@ struct GroupStageView: View {
groupStage._matches().forEach({ $0.updateTeamScores() })
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -230,7 +244,7 @@ struct GroupStageView: View {
private func _save() {
do {
try dataStore.groupStages.addOrUpdate(instance: groupStage)
try tournamentStore.groupStages.addOrUpdate(instance: groupStage)
} catch {
Logger.error(error)
}
@ -238,9 +252,12 @@ struct GroupStageView: View {
}
struct GroupStageNameEditionView: View {
@Environment(\.dismiss) private var dismiss
@Environment(Tournament.self) private var tournament
@EnvironmentObject var dataStore: DataStore
@Bindable var groupStage: GroupStage
@State private var groupStageName: String
@State private var presentConfirmationButton: Bool = false
@ -252,6 +269,10 @@ struct GroupStageNameEditionView: View {
_size = .init(wrappedValue: groupStage.size)
}
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
Form {
Section {
@ -295,7 +316,7 @@ struct GroupStageNameEditionView: View {
groupStage._matches().forEach({ $0.updateTeamScores() })
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: teams)
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: teams)
} catch {
Logger.error(error)
}
@ -344,7 +365,7 @@ struct GroupStageNameEditionView: View {
private func _save() {
do {
try dataStore.groupStages.addOrUpdate(instance: groupStage)
try tournamentStore.groupStages.addOrUpdate(instance: groupStage)
} catch {
Logger.error(error)
}

@ -9,13 +9,20 @@ import SwiftUI
import LeStorage
struct MatchDateView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
var match: Match
var showPrefix: Bool = false
private var isReady: Bool
private var hasWalkoutTeam: Bool
private var hasEnded: Bool
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(match: Match, showPrefix: Bool) {
self.match = match
self.showPrefix = showPrefix
@ -143,7 +150,7 @@ struct MatchDateView: View {
private func _save() {
do {
try dataStore.matches.addOrUpdate(instance: match)
try self.tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}

@ -9,7 +9,10 @@ import SwiftUI
import LeStorage
struct MatchDetailView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var networkMonitor: NetworkMonitor
@Environment(\.dismiss) var dismiss
let matchViewStyle: MatchViewStyle
@ -31,7 +34,11 @@ struct MatchDetailView: View {
@State var showSubscriptionView: Bool = false
@State var showUserCreationView: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var messageSentFailed: Binding<Bool> {
Binding {
sentError != nil
@ -442,7 +449,7 @@ struct MatchDetailView: View {
}
fileprivate func _verifyUser(_ handler: () -> ()) {
if Store.main.userId != nil {
if StoreCenter.main.userId != nil {
handler()
} else {
self.showUserCreationView = true
@ -462,7 +469,7 @@ struct MatchDetailView: View {
private func save() {
do {
try dataStore.matches.addOrUpdate(instance: match)
try self.tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}

@ -8,8 +8,11 @@
import SwiftUI
struct MatchRowView: View {
var match: Match
var tournament: Tournament
let matchViewStyle: MatchViewStyle
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
@ViewBuilder
@ -55,6 +58,7 @@ struct MatchRowView: View {
NavigationLink {
MatchDetailView(match: match, matchViewStyle: matchViewStyle)
.environment(self.tournament)
} label: {
MatchSummaryView(match: match, matchViewStyle: matchViewStyle)
}

@ -9,10 +9,17 @@ import SwiftUI
import LeStorage
struct MatchSetupView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
var match: Match
@State private var seedGroup: SeedInterval?
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
@ViewBuilder
var body: some View {
ForEach(TeamPosition.allCases) { teamPosition in
@ -41,19 +48,19 @@ struct MatchSetupView: View {
match.updateTeamScores()
match.enableMatch()
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
} else {
match.teamWillBeWalkOut(team)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
@ -76,19 +83,19 @@ struct MatchSetupView: View {
if walkOutSpot {
match.setLuckyLoser(team: team, teamPosition: teamPosition)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
} else {
team.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
@ -103,7 +110,7 @@ struct MatchSetupView: View {
if let randomTeam = luckyLosers.randomElement() {
match.setLuckyLoser(team: randomTeam, teamPosition: teamPosition)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
@ -117,12 +124,12 @@ struct MatchSetupView: View {
if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try dataStore.teamRegistrations.addOrUpdate(instance: randomTeam)
try tournamentStore.teamRegistrations.addOrUpdate(instance: randomTeam)
} catch {
Logger.error(error)
}
@ -141,7 +148,7 @@ struct MatchSetupView: View {
Button {
match.unlockSeedPosition(atTeamPosition: teamPosition)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
@ -153,7 +160,7 @@ struct MatchSetupView: View {
Button {
_ = match.lockAndGetSeedPosition(atTeamPosition: teamPosition)
do {
try dataStore.matches.addOrUpdate(instance: match)
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}

@ -10,6 +10,7 @@ import LeStorage
struct MainView: View {
@EnvironmentObject var dataStore: DataStore
@AppStorage("importingFiles") var importingFiles: Bool = false
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
@ -44,14 +45,9 @@ struct MainView: View {
}
}
)}
var matches: [Match] {
return dataStore.matches.filter { match in
match.confirmed && match.startDate != nil && match.endDate == nil && match.courtIndex != nil }
}
private func _isConnected() -> Bool {
return Store.main.hasToken() && Store.main.userId != nil
return StoreCenter.main.hasToken() && StoreCenter.main.userId != nil
}
var badgeText: Text? {
@ -73,7 +69,7 @@ struct MainView: View {
.tabItem(for: .tournamentOrganizer)
OngoingView()
.tabItem(for: .ongoing)
.badge(matches.count)
.badge(self.dataStore.runningMatches().count)
ToolboxView()
.tabItem(for: .toolbox)
UmpireView()
@ -84,7 +80,7 @@ struct MainView: View {
}
.id(mainViewId)
.onChange(of: dataStore.user.id) {
if Store.main.userId == nil { // user disconnected
if StoreCenter.main.userId == nil { // user disconnected
navigation.path.removeLast(navigation.path.count)
mainViewId = UUID()
}
@ -92,7 +88,7 @@ struct MainView: View {
.environmentObject(dataStore)
.task {
await self._checkSourceFileAvailability()
if Store.main.hasToken() {
if StoreCenter.main.hasToken() {
do {
try await dataStore.clubs.loadDataFromServerIfAllowed()
} catch {

@ -9,15 +9,18 @@ import SwiftUI
import LeStorage
struct OngoingView: View {
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
@EnvironmentObject var dataStore: DataStore
@State private var sortByField: Bool = false
let fieldSorting : [MySortDescriptor<Match>] = [.keyPath(\Match.courtIndex!), .keyPath(\Match.startDate!)]
let defaultSorting : [MySortDescriptor<Match>] = [.keyPath(\Match.startDate!), .keyPath(\Match.courtIndex!)]
var matches: [Match] {
let sorting = sortByField ? fieldSorting : defaultSorting
return dataStore.matches.filter({ $0.confirmed && $0.startDate != nil && $0.endDate == nil && $0.courtIndex != nil }).sorted(using: sorting, order: .ascending)
let sorting = self.sortByField ? fieldSorting : defaultSorting
return self.dataStore.runningMatches().sorted(using: sorting, order: .ascending)
}
var body: some View {
@ -26,10 +29,12 @@ struct OngoingView: View {
let matches = matches.filter { $0.currentTournament()?.isDeleted == false }
List {
ForEach(matches) { match in
Section {
MatchRowView(match: match, matchViewStyle: .standardStyle)
} header: {
if let tournament = match.currentTournament() {
if let tournament = match.currentTournament() {
Section {
MatchRowView(match: match, tournament: tournament, matchViewStyle: .standardStyle)
} header: {
HStack {
Text(tournament.tournamentTitle(.short))
Spacer()
@ -37,23 +42,21 @@ struct OngoingView: View {
Text("@" + club.clubTitle(.short))
}
}
} else {
Text("Pas de tournoi")
}
} footer: {
HStack {
if let tournament = match.currentTournament() {
} footer: {
HStack {
Text(tournament.eventLabel())
}
#if DEBUG
Spacer()
FooterButtonView("copier l'id") {
let pasteboard = UIPasteboard.general
pasteboard.string = match.id
}
Spacer()
FooterButtonView("copier l'id") {
let pasteboard = UIPasteboard.general
pasteboard.string = match.id
}
#endif
}
}
}
}
}
.headerProminence(.increased)
@ -74,13 +77,13 @@ struct OngoingView: View {
}
#if DEBUG
Button("effacer les mauvais matchs") {
let bad = matches.filter({ $0.currentTournament() == nil })
do {
try dataStore.matches.delete(contentOfs: bad)
} catch {
Logger.error(error)
}
Button("effacer les mauvais matchs (TODO)") {
// let bad = matches.filter({ $0.currentTournament() == nil })
// do {
// try self.tournamentStore.matches.delete(contentOfs: bad)
// } catch {
// Logger.error(error)
// }
}
#endif
//todo

@ -44,7 +44,7 @@ struct TournamentOrganizerView: View {
}
}
}
.onChange(of: Store.main.userId) {
.onChange(of: StoreCenter.main.userId) {
navigation.organizerTournament = nil
}
}

@ -43,7 +43,7 @@ struct APICallsView: View {
@MainActor
fileprivate func _load() {
Task {
self.text = await Store.main.apiCallsFileContent(resourceName: self.name)
self.text = await StoreCenter.main.apiCallsFileContent(resourceName: self.name)
}
}

@ -21,15 +21,15 @@ struct DebugSettingsView: View {
}
fileprivate var _userId: String {
return Store.main.userId ?? ""
return StoreCenter.main.userId ?? ""
}
fileprivate var _userName: String {
return Store.main.userName() ?? ""
return StoreCenter.main.userName() ?? ""
}
fileprivate var _token: String {
return Store.main.token() ?? ""
return StoreCenter.main.token() ?? ""
}
fileprivate var _server: String {
@ -45,7 +45,7 @@ struct DebugSettingsView: View {
}
fileprivate var _canSynchronize: String {
return "\(Store.main.collectionsCanSynchronize)"
return "\(StoreCenter.main.collectionsCanSynchronize)"
}
}

@ -10,6 +10,7 @@ import LeStorage
struct ToolboxView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(NavigationViewModel.self) private var navigation: NavigationViewModel
var body: some View {
@ -21,7 +22,7 @@ struct ToolboxView: View {
Text("Version de l'application").badge(PadelClubApp.appVersion)
SupportButtonView(contentIsUnavailable: false)
if Store.main.userId == "94f45ed2-8938-4c32-a4b6-e4525073dd33" {
if StoreCenter.main.userId == "94f45ed2-8938-4c32-a4b6-e4525073dd33" {
Button {
Patcher.applyPatch(.alexisLeDu)
} label: {
@ -52,45 +53,64 @@ struct ToolboxView: View {
Section {
RowButtonView("Reset ALL API Calls") {
Store.main.resetApiCalls()
StoreCenter.main.resetApiCalls()
Logger.log("Api calls reset")
}
}
Section {
RowButtonView("Fix Names") {
let playerRegistrations = dataStore.playerRegistrations
playerRegistrations.forEach { player in
player.firstName = player.firstName.trimmed.capitalized
player.lastName = player.lastName.trimmed.uppercased()
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: playerRegistrations)
} catch {
Logger.error(error)
for tournament in dataStore.tournaments {
let store = tournament.tournamentStore
let playerRegistrations = store.playerRegistrations
playerRegistrations.forEach { player in
player.firstName = player.firstName.trimmed.capitalized
player.lastName = player.lastName.trimmed.uppercased()
}
do {
try store.playerRegistrations.addOrUpdate(contentOfs: playerRegistrations)
} catch {
Logger.error(error)
}
}
}
}
Section {
RowButtonView("Delete teams") {
let teamRegistrations = dataStore.teamRegistrations.filter({ $0.tournamentObject() == nil })
do {
try dataStore.teamRegistrations.delete(contentOfs: teamRegistrations)
} catch {
Logger.error(error)
for tournament in DataStore.shared.tournaments {
let store: TournamentStore = tournament.tournamentStore
let teamRegistrations = store.teamRegistrations.filter({ $0.tournamentObject() == nil })
do {
try store.teamRegistrations.delete(contentOfs: teamRegistrations)
} catch {
Logger.error(error)
}
}
}
}
Section {
// TODO
RowButtonView("Delete players") {
let playersRegistrations = dataStore.playerRegistrations.filter({ $0.team() == nil })
do {
try dataStore.playerRegistrations.delete(contentOfs: playersRegistrations)
} catch {
Logger.error(error)
for tournament in DataStore.shared.tournaments {
let store: TournamentStore = tournament.tournamentStore
let playersRegistrations = store.playerRegistrations.filter({ $0.team() == nil })
do {
try store.playerRegistrations.delete(contentOfs: playersRegistrations)
} catch {
Logger.error(error)
}
}
}
}

@ -172,7 +172,7 @@ struct UmpireView: View {
.toolbar {
#if DEBUG
ToolbarItem(placement: .topBarTrailing) {
if Store.main.collectionsCanSynchronize {
if StoreCenter.main.collectionsCanSynchronize {
Image(systemName: "checkmark.icloud")
} else {
Image(systemName: "icloud.slash")
@ -193,7 +193,7 @@ struct UmpireView: View {
user.licenceId = player.license
if user.clubsObjects().contains(where: { $0.code == player.clubCode }) == false {
let userClub = Club.findOrCreate(name: player.clubName!, code: player.clubCode)
if userClub.hasBeenCreated(by: Store.main.userId) {
if userClub.hasBeenCreated(by: StoreCenter.main.userId) {
do {
try dataStore.clubs.addOrUpdate(instance: userClub)
} catch {
@ -224,7 +224,7 @@ struct UmpireView: View {
}
fileprivate func _isConnected() -> Bool {
return dataStore.user.username.count > 0 && Store.main.hasToken()
return dataStore.user.username.count > 0 && StoreCenter.main.hasToken()
}
}
@ -235,11 +235,11 @@ struct AccountRowView: View {
var userName: String
var body: some View {
let hasToken = Store.main.hasToken()
let hasToken = StoreCenter.main.hasToken()
LabeledContent {
if hasToken {
Text(self.userName)
} else if Store.main.userName() != nil {
} else if StoreCenter.main.userName() != nil {
Image(systemName: "xmark.circle.fill")
.foregroundStyle(.logoRed)
}

@ -9,11 +9,17 @@ import SwiftUI
import LeStorage
struct GroupStageScheduleEditorView: View {
@EnvironmentObject var dataStore: DataStore
@Bindable var groupStage: GroupStage
var tournament: Tournament
@State private var startDate: Date
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(groupStage: GroupStage, tournament: Tournament) {
self.groupStage = groupStage
self.tournament = tournament
@ -29,7 +35,7 @@ struct GroupStageScheduleEditorView: View {
private func _save() {
do {
try dataStore.groupStages.addOrUpdate(instance: groupStage)
try tournamentStore.groupStages.addOrUpdate(instance: groupStage)
} catch {
Logger.error(error)
}

@ -9,14 +9,19 @@ import SwiftUI
import LeStorage
struct LoserRoundScheduleEditorView: View {
@EnvironmentObject var dataStore: DataStore
var upperRound: Round
var tournament: Tournament
var loserRounds: [Round]
@State private var startDate: Date
@State private var matchFormat: MatchFormat
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(upperRound: Round, tournament: Tournament) {
self.upperRound = upperRound
self.tournament = tournament
@ -75,7 +80,7 @@ struct LoserRoundScheduleEditorView: View {
private func _save() {
do {
try dataStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds())
try self.tournamentStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds())
} catch {
Logger.error(error)
}

@ -9,6 +9,7 @@ import SwiftUI
import LeStorage
struct LoserRoundStepScheduleEditorView: View {
@EnvironmentObject var dataStore: DataStore
var stepIndex: Int
@ -18,7 +19,11 @@ struct LoserRoundStepScheduleEditorView: View {
var matches: [Match]
@State private var startDate: Date
//@State private var matchFormat: MatchFormat
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(stepIndex: Int, round: Round, upperRound: Round, tournament: Tournament) {
self.upperRound = upperRound
self.tournament = tournament
@ -69,7 +74,7 @@ struct LoserRoundStepScheduleEditorView: View {
private func _save() {
do {
try dataStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds(forRoundIndex: round.index))
try tournamentStore.rounds.addOrUpdate(contentOfs: upperRound.loserRounds(forRoundIndex: round.index))
} catch {
Logger.error(error)
}

@ -9,7 +9,9 @@ import SwiftUI
import LeStorage
struct PlanningSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@Bindable var tournament: Tournament
@Bindable var matchScheduler: MatchScheduler
@ -20,6 +22,10 @@ struct PlanningSettingsView: View {
@State private var issueFound: Bool = false
@State private var parallelType: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(tournament: Tournament) {
self.tournament = tournament
if let matchScheduler = tournament.matchScheduler() {
@ -68,7 +74,7 @@ struct PlanningSettingsView: View {
let verb = tournament.courtCount > 1 ? "seront" : "sera"
Text("En réduisant les terrains maximum, seul\(plural) le\(plural) \(tournament.courtCount) premier\(plural) terrain\(plural) \(verb) utilisé\(plural)") + Text(", par contre, si vous augmentez le nombre de terrains, vous pourrez plutôt préciser quel terrain n'est pas disponible.")
} else if tournament.courtCount > club.courtCount {
let isCreatedByUser = club.hasBeenCreated(by: Store.main.userId)
let isCreatedByUser = club.hasBeenCreated(by: StoreCenter.main.userId)
Button {
do {
club.courtCount = tournament.courtCount
@ -117,7 +123,7 @@ struct PlanningSettingsView: View {
$0.startDate = nil
$0.confirmed = false
})
try dataStore.matches.addOrUpdate(contentOfs: allMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
} catch {
Logger.error(error)
}
@ -133,13 +139,13 @@ struct PlanningSettingsView: View {
$0.startDate = nil
$0.confirmed = false
})
try dataStore.matches.addOrUpdate(contentOfs: allMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
allGroupStages.forEach({ $0.startDate = nil })
try dataStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
allRounds.forEach({ $0.startDate = nil })
try dataStore.rounds.addOrUpdate(contentOfs: allRounds)
try self.tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
} catch {
Logger.error(error)
}
@ -172,7 +178,7 @@ struct PlanningSettingsView: View {
.headerProminence(.increased)
.onAppear {
do {
try dataStore.matchSchedulers.addOrUpdate(instance: matchScheduler)
try self.tournamentStore.matchSchedulers.addOrUpdate(instance: matchScheduler)
} catch {
Logger.error(error)
}
@ -306,7 +312,7 @@ struct PlanningSettingsView: View {
private func _save() {
do {
try dataStore.matchSchedulers.addOrUpdate(instance: matchScheduler)
try self.tournamentStore.matchSchedulers.addOrUpdate(instance: matchScheduler)
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)

@ -37,6 +37,7 @@ struct PlanningView: View {
ForEach(_matches) { match in
NavigationLink {
MatchDetailView(match: match, matchViewStyle: .sectionedStandardStyle)
.environment(self.tournament)
} label: {
LabeledContent {
if let courtName = match.courtName() {

@ -14,7 +14,11 @@ struct RoundScheduleEditorView: View {
var round: Round
var tournament: Tournament
@State private var startDate: Date
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(round: Round, tournament: Tournament) {
self.round = round
self.tournament = tournament
@ -62,7 +66,7 @@ struct RoundScheduleEditorView: View {
private func _save() {
do {
try dataStore.rounds.addOrUpdate(instance: round)
try tournamentStore.rounds.addOrUpdate(instance: round)
} catch {
Logger.error(error)
}

@ -20,10 +20,16 @@ extension Round: Schedulable {
}
struct SchedulerView: View {
@EnvironmentObject var dataStore: DataStore
var tournament: Tournament
var destination: ScheduleDestination
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
@Bindable var tournament = tournament
@ -43,7 +49,7 @@ struct SchedulerView: View {
}
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: groupStages)
} catch {
Logger.error(error)
}
@ -82,7 +88,7 @@ struct SchedulerView: View {
do {
try dataStore.tournaments.addOrUpdate(instance: tournament)
try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: groupStages)
} catch {
Logger.error(error)
}
@ -122,7 +128,7 @@ struct SchedulerView: View {
Button {
round.updateMatchFormatAndAllMatches(federalFormat)
do {
try dataStore.rounds.addOrUpdate(instance: round)
try self.tournamentStore.rounds.addOrUpdate(instance: round)
} catch {
Logger.error(error)
}
@ -166,7 +172,7 @@ struct SchedulerView: View {
Button {
round.updateMatchFormatAndAllMatches(federalFormat)
do {
try dataStore.rounds.addOrUpdate(instance: round)
try self.tournamentStore.rounds.addOrUpdate(instance: round)
} catch {
Logger.error(error)
}

@ -17,6 +17,8 @@ struct EditablePlayerView: View {
}
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@Bindable var player: PlayerRegistration
var editingOptions: [PlayerEditingOption]
@State private var editedLicenceId = ""
@ -24,6 +26,10 @@ struct EditablePlayerView: View {
@State private var presentLastNameUpdate: Bool = false
@State private var presentFirstNameUpdate: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
computedPlayerView(player)
.alert("Numéro de licence", isPresented: $shouldPresentLicenceIdEdition) {
@ -32,7 +38,7 @@ struct EditablePlayerView: View {
player.licenceId = editedLicenceId
editedLicenceId = ""
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try self.tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}
@ -42,7 +48,7 @@ struct EditablePlayerView: View {
TextField("Prénom", text: $player.firstName)
.onSubmit {
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try self.tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}
@ -52,7 +58,7 @@ struct EditablePlayerView: View {
TextField("Nom", text: $player.lastName)
.onSubmit {
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try self.tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}
@ -74,7 +80,7 @@ struct EditablePlayerView: View {
Button {
player.hasArrived.toggle()
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try self.tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}

@ -9,9 +9,14 @@ import SwiftUI
import LeStorage
struct PlayerPayView: View {
@EnvironmentObject var dataStore: DataStore
@Bindable var player: PlayerRegistration
@Environment(Tournament.self) var tournament: Tournament
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
Picker(selection: $player.paymentType) {
Text("Non réglé").tag(nil as PlayerRegistration.PlayerPaymentType?)
@ -29,7 +34,7 @@ struct PlayerPayView: View {
private func _save() {
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}

@ -8,10 +8,16 @@
import SwiftUI
struct PlayerSexPickerView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@Bindable var player: PlayerRegistration
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
HStack {
Text(player.playerLabel())
@ -33,10 +39,10 @@ struct PlayerSexPickerView: View {
private func _save() {
do {
player.setComputedRank(in: tournament)
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try tournamentStore.playerRegistrations.addOrUpdate(instance: player)
if let team = player.team() {
team.updateWeight(inTournamentCategory: tournament.tournamentCategory)
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
}
} catch {

@ -9,14 +9,20 @@ import SwiftUI
import LeStorage
struct PlayerDetailView: View {
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var dataStore: DataStore
@Bindable var player: PlayerRegistration
@State private var licenceId: String
@State private var phoneNumber: String
@State private var email: String
@FocusState var focusedField: PlayerRegistration.CodingKeys?
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(player: PlayerRegistration) {
self.player = player
_licenceId = .init(wrappedValue: player.licenceId ?? "")
@ -205,13 +211,13 @@ struct PlayerDetailView: View {
private func _save() {
do {
try dataStore.playerRegistrations.addOrUpdate(instance: player)
try self.tournamentStore.playerRegistrations.addOrUpdate(instance: player)
} catch {
Logger.error(error)
}
if let team = player.team() {
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try self.tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}

@ -9,15 +9,22 @@ import SwiftUI
import LeStorage
struct PlayerView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
let player: PlayerRegistration
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
ImportedPlayerView(player: player)
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button(role: .destructive) {
do {
try dataStore.playerRegistrations.delete(instance: player)
try self.tournamentStore.playerRegistrations.delete(instance: player)
} catch {
Logger.error(error)
}

@ -29,7 +29,7 @@ struct LoserRoundView: View {
Section {
let matches = loserRound.playedMatches().sorted(by: \.index)
ForEach(matches) { match in
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle)
MatchRowView(match: match, tournament: self.tournament, matchViewStyle: .sectionedStandardStyle)
.overlay {
if match.disabled /*&& isEditingTournamentSeed*/ {
Image(systemName: "xmark")

@ -10,9 +10,14 @@ import LeStorage
struct RoundSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
@Environment(Tournament.self) var tournament: Tournament
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
List {
if tournament.shouldVerifyBracket {
@ -78,12 +83,12 @@ struct RoundSettingsView: View {
return match
}
do {
try dataStore.rounds.addOrUpdate(instance: round)
try tournamentStore.rounds.addOrUpdate(instance: round)
} catch {
Logger.error(error)
}
do {
try dataStore.matches.addOrUpdate(contentOfs: matches)
try tournamentStore.matches.addOrUpdate(contentOfs: matches)
} catch {
Logger.error(error)
}
@ -97,7 +102,7 @@ struct RoundSettingsView: View {
if let lastRound = tournament.rounds().first { // first is final, last round
RowButtonView("Supprimer " + lastRound.roundTitle(), role: .destructive) {
do {
try dataStore.rounds.delete(instance: lastRound)
try tournamentStore.rounds.delete(instance: lastRound)
} catch {
Logger.error(error)
}
@ -116,12 +121,12 @@ struct RoundSettingsView: View {
}
do {
try DataStore.shared.teamScores.delete(contentOfs: ts)
try tournamentStore.teamScores.delete(contentOfs: ts)
} catch {
Logger.error(error)
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
} catch {
Logger.error(error)
}

@ -10,6 +10,7 @@ import LeStorage
import TipKit
struct RoundView: View {
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var dataStore: DataStore
@ -23,6 +24,10 @@ struct RoundView: View {
var round: Round
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
private func _getAvailableSeedGroup() async {
availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: round.index)
}
@ -226,7 +231,7 @@ struct RoundView: View {
ForEach(displayableMatches) { match in
Section {
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle)
MatchRowView(match: match, tournament: self.tournament, matchViewStyle: .sectionedStandardStyle)
} header: {
HStack {
Text(round.roundTitle(.wide))
@ -298,7 +303,7 @@ struct RoundView: View {
private func _save() async {
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
} catch {
Logger.error(error)
}
@ -313,7 +318,7 @@ struct RoundView: View {
}
let allRoundMatches = tournament.allRoundMatches()
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: allRoundMatches)
try self.tournamentStore.matches.addOrUpdate(contentOfs: allRoundMatches)
} catch {
Logger.error(error)
}

@ -9,10 +9,17 @@ import SwiftUI
import LeStorage
struct EditScoreView: View {
@EnvironmentObject var dataStore: DataStore
@ObservedObject var matchDescriptor: MatchDescriptor
@Environment(\.dismiss) private var dismiss
@Environment(Tournament.self) var tournament: Tournament
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
func walkout(_ team: TeamPosition) {
self.matchDescriptor.match?.setWalkOut(team)
save()
@ -104,7 +111,7 @@ struct EditScoreView: View {
func save() {
if let match = matchDescriptor.match {
do {
try dataStore.matches.addOrUpdate(instance: match)
try self.tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}

@ -80,7 +80,7 @@ struct SupportButtonView: View {
private func _getBody() -> String {
let separator = "---------------------------------------------"
return ["Décrivez votre problème", "\n\n\n", separator, "token", Store.main.token(), separator, "userId", Store.main.userId, separator, "dataStore userId", DataStore.shared.user.id].compacted().joined(separator: "\n")
return ["Décrivez votre problème", "\n\n\n", separator, "token", StoreCenter.main.token(), separator, "userId", StoreCenter.main.userId, separator, "dataStore userId", DataStore.shared.user.id].compacted().joined(separator: "\n")
}
private func _getDeviceIdentifier() -> String {

@ -10,10 +10,17 @@ import LeStorage
struct EditingTeamView: View {
@EnvironmentObject var dataStore: DataStore
var team: TeamRegistration
@State private var registrationDate : Date
@State private var name: String
@Environment(Tournament.self) var tournament: Tournament
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
init(team: TeamRegistration) {
self.team = team
_name = .init(wrappedValue: team.name ?? "")
@ -91,7 +98,7 @@ struct EditingTeamView: View {
$0.hasArrived = hasArrived
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: team.unsortedPlayers())
try tournamentStore.playerRegistrations.addOrUpdate(contentOfs: team.unsortedPlayers())
} catch {
Logger.error(error)
}
@ -100,7 +107,7 @@ struct EditingTeamView: View {
}
private func _save() {
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}

@ -55,7 +55,9 @@ enum FileImportCustomField: Int, Identifiable, CaseIterable {
}
struct FileImportView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(Tournament.self) var tournament: Tournament
@Environment(\.dismiss) private var dismiss
@ -76,6 +78,10 @@ struct FileImportView: View {
@State private var multiImport: Bool = false
@State private var presentFormatHelperView: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
private func filteredTeams(tournament: Tournament) -> [FileImportManager.TeamHolder] {
return teams.filter { $0.tournamentCategory == tournament.tournamentCategory }.sorted(by: \.weight)
}
@ -83,7 +89,7 @@ struct FileImportView: View {
private func _deleteTeams() async {
await MainActor.run {
do {
try dataStore.teamRegistrations.delete(contentOfs: tournament.unsortedTeams())
try tournamentStore.teamRegistrations.delete(contentOfs: tournament.unsortedTeams())
} catch {
Logger.error(error)
}
@ -417,7 +423,7 @@ struct FileImportView: View {
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: unfound)
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unfound)
} catch {
Logger.error(error)
}

@ -32,7 +32,7 @@ struct BroadcastView: View {
var body: some View {
@Bindable var tournament = tournament
List {
if Store.main.userId == nil {
if StoreCenter.main.userId == nil {
Section {
TipView(createAccountTip) { action in
switch action.id {

@ -75,7 +75,7 @@ struct TournamentClubSettingsView: View {
let verb = tournament.courtCount > 1 ? "seront" : "sera"
Text("En réduisant les terrains maximum, seul\(plural) le\(plural) \(tournament.courtCount) premier\(plural) terrain\(plural) \(verb) utilisé\(plural)") + Text(", par contre, si vous augmentez le nombre de terrains, vous pourrez plutôt préciser quel terrain n'est pas disponible.")
} else if tournament.courtCount > club.courtCount {
let isCreatedByUser = club.hasBeenCreated(by: Store.main.userId)
let isCreatedByUser = club.hasBeenCreated(by: StoreCenter.main.userId)
Button {
do {
club.courtCount = tournament.courtCount
@ -100,7 +100,7 @@ struct TournamentClubSettingsView: View {
if let selectedClub {
ClubCourtSetupView(club: selectedClub, displayContext: selectedClub.hasBeenCreated(by: Store.main.userId) ? .edition : .lockedForEditing, selectedCourt: $selectedCourt)
ClubCourtSetupView(club: selectedClub, displayContext: selectedClub.hasBeenCreated(by: StoreCenter.main.userId) ? .edition : .lockedForEditing, selectedCourt: $selectedCourt)
.onChange(of: selectedClub.courtCount) {
tournament.courtCount = max(tournament.courtCount, selectedClub.courtCount)
do {
@ -112,7 +112,7 @@ struct TournamentClubSettingsView: View {
}
}
.navigationDestination(item: $showClubDetail) { club in
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: Store.main.userId) ? .edition : .lockedForEditing)
ClubDetailView(club: club, displayContext: club.hasBeenCreated(by: StoreCenter.main.userId) ? .edition : .lockedForEditing)
}
.navigationDestination(item: $selectedCourt) { court in
CourtView(court: court)

@ -9,11 +9,18 @@ import SwiftUI
import LeStorage
struct TournamentMatchFormatsSettingsView: View {
@Environment(NavigationViewModel.self) var navigation: NavigationViewModel
@Environment(Tournament.self) var tournament: Tournament
@EnvironmentObject var dataStore: DataStore
@State private var confirmUpdate: Bool = false
@State private var updateCompleted: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
@Bindable var tournament = tournament
List {
@ -92,12 +99,12 @@ struct TournamentMatchFormatsSettingsView: View {
}
}
do {
try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
try tournamentStore.groupStages.addOrUpdate(contentOfs: groupStages)
} catch {
Logger.error(error)
}
do {
try dataStore.rounds.addOrUpdate(contentOfs: allRounds)
try tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
} catch {
Logger.error(error)
}

@ -10,12 +10,17 @@ import LeStorage
struct UpdateSourceRankDateView: View {
@EnvironmentObject var dataStore: DataStore
@Binding var currentRankSourceDate: Date?
@Binding var confirmUpdateRank: Bool
@State private var forceRefreshLockWeight: Bool = false
@State private var updatingRank = false
var tournament: Tournament
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var body: some View {
NavigationStack {
List {
@ -43,7 +48,7 @@ struct UpdateSourceRankDateView: View {
player.setComputedRank(in: tournament)
}
try dataStore.playerRegistrations.addOrUpdate(contentOfs: tournament.unsortedPlayers())
try tournamentStore.playerRegistrations.addOrUpdate(contentOfs: tournament.unsortedPlayers())
tournament.unsortedTeams().forEach { team in
team.setWeight(from: team.players(), inTournamentCategory: tournament.tournamentCategory)
@ -52,7 +57,7 @@ struct UpdateSourceRankDateView: View {
}
}
try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
try dataStore.tournaments.addOrUpdate(instance: tournament)

@ -20,7 +20,9 @@ let padelBeachExportTip = PadelBeachExportTip()
let padelBeachImportTip = PadelBeachImportTip()
struct InscriptionManagerView: View {
@EnvironmentObject var dataStore: DataStore
@EnvironmentObject var networkMonitor: NetworkMonitor
@Environment(\.dismiss) var dismiss
@ -63,6 +65,10 @@ struct InscriptionManagerView: View {
@State private var teamPaste: URL?
@State private var confirmDuplicate: Bool = false
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var messageSentFailed: Binding<Bool> {
Binding {
sentError != nil
@ -167,7 +173,7 @@ struct InscriptionManagerView: View {
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: waitingList)
try tournamentStore.teamRegistrations.addOrUpdate(contentOfs: waitingList)
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)
@ -887,12 +893,12 @@ struct InscriptionManagerView: View {
let players = _currentSelection()
let team = tournament.addTeam(players)
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try self.tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: players)
try self.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
@ -915,12 +921,12 @@ struct InscriptionManagerView: View {
let players = _currentSelection()
editedTeam.updatePlayers(players, inTournamentCategory: tournament.tournamentCategory)
do {
try dataStore.teamRegistrations.addOrUpdate(instance: editedTeam)
try self.tournamentStore.teamRegistrations.addOrUpdate(instance: editedTeam)
} catch {
Logger.error(error)
}
do {
try dataStore.playerRegistrations.addOrUpdate(contentOfs: players)
try self.tournamentStore.playerRegistrations.addOrUpdate(contentOfs: players)
} catch {
Logger.error(error)
}
@ -1151,7 +1157,7 @@ struct InscriptionManagerView: View {
team.walkOut = false
team.wildCardBracket = value
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
@ -1172,7 +1178,7 @@ struct InscriptionManagerView: View {
team.walkOut = false
team.wildCardGroupStage = value
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
@ -1193,7 +1199,7 @@ struct InscriptionManagerView: View {
team.wildCardGroupStage = false
team.walkOut = value
do {
try dataStore.teamRegistrations.addOrUpdate(instance: team)
try tournamentStore.teamRegistrations.addOrUpdate(instance: team)
} catch {
Logger.error(error)
}
@ -1207,7 +1213,7 @@ struct InscriptionManagerView: View {
_clearScreen()
Task {
do {
try dataStore.teamRegistrations.delete(instance: team)
try tournamentStore.teamRegistrations.delete(instance: team)
} catch {
Logger.error(error)
}

@ -15,7 +15,11 @@ struct TournamentRankView: View {
@State private var rankings: [Int: [TeamRegistration]] = [:]
@State private var calculating = false
@State private var selectedTeam: TeamRegistration?
var tournamentStore: TournamentStore {
return self.tournament.tournamentStore
}
var isEditingTeam: Binding<Bool> {
Binding {
selectedTeam != nil
@ -121,7 +125,7 @@ struct TournamentRankView: View {
Button("Valider") {
selectedTeam.pointsEarned = tournament.isAnimation() ? nil : tournament.tournamentLevel.points(for: selectedTeam.finalRanking! - 1, count: tournament.teamCount)
do {
try dataStore.teamRegistrations.addOrUpdate(instance: selectedTeam)
try self.tournamentStore.teamRegistrations.addOrUpdate(instance: selectedTeam)
} catch {
Logger.error(error)
}
@ -254,7 +258,8 @@ struct TournamentRankView: View {
let finalRanks = await tournament.finalRanking()
finalRanks.keys.sorted().forEach { rank in
if let rankedTeamIds = finalRanks[rank] {
rankings[rank] = rankedTeamIds.compactMap { Store.main.findById($0) }
let teams: [TeamRegistration] = rankedTeamIds.compactMap { self.tournamentStore.teamRegistrations.findById($0) }
self.rankings[rank] = teams
}
}
}
@ -281,7 +286,7 @@ struct TournamentRankView: View {
private func _save() {
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
} catch {
Logger.error(error)
}

@ -14,7 +14,7 @@ struct TournamentBroadcastRowView: View {
var body: some View {
NavigationLink(value: Screen.broadcast) {
LabeledContent {
if Store.main.userId == nil {
if StoreCenter.main.userId == nil {
Image(systemName: "exclamationmark.circle.fill")
.foregroundStyle(.logoYellow)
} else {
@ -26,7 +26,7 @@ struct TournamentBroadcastRowView: View {
}
} label: {
Text("Publication")
if Store.main.userId == nil {
if StoreCenter.main.userId == nil {
Text("Créez un compte pour publier !")
}
}

@ -153,7 +153,7 @@ import LeStorage
func userFilteredPurchases() -> [StoreKit.Transaction] {
// Logger.log("self.purchasedTransactions = \(self.purchasedTransactions.count)")
guard let userId = Store.main.userId, let currentUserUUID: UUID = UUID(uuidString: userId) else {
guard let userId = StoreCenter.main.userId, let currentUserUUID: UUID = UUID(uuidString: userId) else {
return []
}
@ -250,7 +250,7 @@ struct PurchaseRow: Identifiable {
fileprivate extension StoreKit.Transaction {
func purchase() throws -> Purchase {
guard let userId = Store.main.userId else {
guard let userId = StoreCenter.main.userId else {
throw StoreError.missingUserId
}
return Purchase(user: userId,

@ -9,10 +9,10 @@ import Foundation
import LeStorage
class Purchase: ModelObject, Storable {
static func resourceName() -> String { return "purchases" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
var id: String = Store.randomId()
var user: String

@ -100,7 +100,7 @@ class StoreManager {
func purchase(_ product: Product, quantity: Int? = nil) async throws -> StoreKit.Transaction? {
Logger.log("Store purchase started...")
guard let userId = Store.main.userId, let uuid: UUID = UUID(uuidString: userId) else {
guard let userId = StoreCenter.main.userId, let uuid: UUID = UUID(uuidString: userId) else {
throw StoreError.missingUserId
}

@ -203,7 +203,7 @@ struct SubscriptionView: View {
}
fileprivate func _purchaseIfPossible() {
if Store.main.userId != nil {
if StoreCenter.main.userId != nil {
self._purchase()
} else {
self.showLoginView = true

@ -11,6 +11,7 @@ import TipKit
struct TournamentView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(NavigationViewModel.self) var navigation: NavigationViewModel
@State var tournament: Tournament
var presentationContext: PresentationContext = .agenda
@ -22,7 +23,7 @@ struct TournamentView: View {
get: { tournament.id },
set: { id in
if let tournamentFound: Tournament = Store.main.findById(id) {
tournament = tournamentFound
self.tournament = tournamentFound
}
}
)}
@ -35,6 +36,11 @@ struct TournamentView: View {
guard let lastDataSource else { return nil }
return URL.importDateFormatter.date(from: lastDataSource)
}
init(tournament: Tournament, presentationContext: PresentationContext = .agenda) {
self.tournament = tournament
self.presentationContext = presentationContext
}
var body: some View {
VStack(spacing: 0.0) {

@ -66,7 +66,7 @@ struct ChangePasswordView: View {
Task {
do {
self.isLoading = true
let service = try Store.main.service()
let service = try StoreCenter.main.service()
_ = try await service.changePassword(
oldPassword: self.oldPassword,
password1: self.password1,

@ -197,7 +197,7 @@ struct LoginView: View {
self.errorText = nil // reset error
self.isLoading = true
do {
let service = try Store.main.service()
let service = try StoreCenter.main.service()
let user: User = try await service.login(
username: self.username,
password: self.password)
@ -240,7 +240,7 @@ struct EmailConfirmationView: View {
Task {
do {
let service = try Store.main.service()
let service = try StoreCenter.main.service()
try await service.forgotPassword(email: self.email)
} catch {
Logger.error(error)

@ -224,7 +224,7 @@ struct UserCreationFormView: View {
phone: self.phone,
country: country)
let service: Services = try Store.main.service()
let service: Services = try StoreCenter.main.service()
let _: User = try await service.createAccount(user: userCreationForm)
DispatchQueue.main.async {

@ -72,7 +72,7 @@ final class ServerDataTests: XCTestCase {
func testEvent() async throws {
guard let userId = Store.main.userId else {
guard let userId = StoreCenter.main.userId else {
assertionFailure("missing user UUID")
return
}
@ -340,7 +340,7 @@ final class ServerDataTests: XCTestCase {
func testPurchase() async throws {
guard let userId = Store.main.userId else {
guard let userId = StoreCenter.main.userId else {
assertionFailure("missing user UUID")
return
}

Loading…
Cancel
Save